I implemented Google OAUTH used google API:
AuthorizationCodeMvcApp authorizationCodeMvcApp = new AuthorizationCodeMvcApp(controller, flowData);
AuthorizationCodeWebApp.AuthResult authorizationResult = await authorizationCodeMvcApp.AuthorizeAsync(CancellationToken.None);
with custom FlowMetadata where override:
public override string AuthCallback
{
get
{
string controllerName = nameof(BillsEmailsConfigurationController);
controllerName = SubstringController(controllerName);
string actionName = "Callback";
return $"/{controllerName}/{actionName}";
}
}
everything works fine but in the production Server, we have a load balancing where the local protocol is HTTP, and only outside we use HTTPS, how to force to put HTTPS prefix to callback for google OAuth API?
ps. return full URL like 'https://..../Callback' doesn't work
Found out the solution is to write custom AuthorizationCodeMvcApp that implemented from AuthorizationCodeWebApp here is the source https://github.com/googleapis/google-api-dotnet-client/blob/master/Src/Support/Google.Apis.Auth.Mvc/OAuth2/Mvc/AuthorizationCodeMvcApp.cs
and in line #46 you can see the passing of the full callback URL
Related
I'm developing an ASP.Net Core web application where I need to create a kind of "authentication proxy" to another (external) web service.
What I mean by authentication proxy is that I will receive requests through a specific path of my web app and will have to check the headers of those requests for an authentication token that I'll have issued earlier, and then redirect all the requests with the same request string / content to an external web API which my app will authenticate with through HTTP Basic auth.
Here's the whole process in pseudo-code
Client requests a token by making a POST to a unique URL that I sent him earlier
My app sends him a unique token in response to this POST
Client makes a GET request to a specific URL of my app, say /extapi and adds the auth-token in the HTTP header
My app gets the request, checks that the auth-token is present and valid
My app does the same request to the external web API and authenticates the request using BASIC authentication
My app receives the result from the request and sends it back to the client
Here's what I have for now. It seems to be working fine, but I'm wondering if it's really the way this should be done or if there isn't a more elegant or better solution to this? Could that solution create issues in the long run for scaling the application?
[HttpGet]
public async Task GetStatement()
{
//TODO check for token presence and reject if issue
var queryString = Request.QueryString;
var response = await _httpClient.GetAsync(queryString.Value);
var content = await response.Content.ReadAsStringAsync();
Response.StatusCode = (int)response.StatusCode;
Response.ContentType = response.Content.Headers.ContentType.ToString();
Response.ContentLength = response.Content.Headers.ContentLength;
await Response.WriteAsync(content);
}
[HttpPost]
public async Task PostStatement()
{
using (var streamContent = new StreamContent(Request.Body))
{
//TODO check for token presence and reject if issue
var response = await _httpClient.PostAsync(string.Empty, streamContent);
var content = await response.Content.ReadAsStringAsync();
Response.StatusCode = (int)response.StatusCode;
Response.ContentType = response.Content.Headers.ContentType?.ToString();
Response.ContentLength = response.Content.Headers.ContentLength;
await Response.WriteAsync(content);
}
}
_httpClient being a HttpClient class instantiated somewhere else and being a singleton and with a BaseAddressof http://someexternalapp.com/api/
Also, is there a simpler approach for the token creation / token check than doing it manually?
If anyone is interested, I took the Microsoft.AspNetCore.Proxy code and made it a little better with middleware.
Check it out here: https://github.com/twitchax/AspNetCore.Proxy. NuGet here: https://www.nuget.org/packages/AspNetCore.Proxy/. Microsoft archived the other one mentioned in this post, and I plan on responding to any issues on this project.
Basically, it makes reverse proxying another web server a lot easier by allowing you to use attributes on methods that take a route with args and compute the proxied address.
[ProxyRoute("api/searchgoogle/{query}")]
public static Task<string> SearchGoogleProxy(string query)
{
// Get the proxied address.
return Task.FromResult($"https://www.google.com/search?q={query}");
}
I ended up implementing a proxy middleware inspired by a project in Asp.Net's GitHub.
It basically implements a middleware that reads the request received, creates a copy from it and sends it back to a configured service, reads the response from the service and sends it back to the caller.
This post talks about writing a simple HTTP proxy logic in C# or ASP.NET Core. And allowing your project to proxy the request to any other URL. It is not about deploying a proxy server for your ASP.NET Core project.
Add the following code anywhere of your project.
public static HttpRequestMessage CreateProxyHttpRequest(this HttpContext context, Uri uri)
{
var request = context.Request;
var requestMessage = new HttpRequestMessage();
var requestMethod = request.Method;
if (!HttpMethods.IsGet(requestMethod) &&
!HttpMethods.IsHead(requestMethod) &&
!HttpMethods.IsDelete(requestMethod) &&
!HttpMethods.IsTrace(requestMethod))
{
var streamContent = new StreamContent(request.Body);
requestMessage.Content = streamContent;
}
// Copy the request headers
foreach (var header in request.Headers)
{
if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
}
}
requestMessage.Headers.Host = uri.Authority;
requestMessage.RequestUri = uri;
requestMessage.Method = new HttpMethod(request.Method);
return requestMessage;
}
This method covert user sends HttpContext.Request to a reusable HttpRequestMessage. So you can send this message to the target server.
After your target server response, you need to copy the responded HttpResponseMessage to the HttpContext.Response so the user's browser just gets it.
public static async Task CopyProxyHttpResponse(this HttpContext context, HttpResponseMessage responseMessage)
{
if (responseMessage == null)
{
throw new ArgumentNullException(nameof(responseMessage));
}
var response = context.Response;
response.StatusCode = (int)responseMessage.StatusCode;
foreach (var header in responseMessage.Headers)
{
response.Headers[header.Key] = header.Value.ToArray();
}
foreach (var header in responseMessage.Content.Headers)
{
response.Headers[header.Key] = header.Value.ToArray();
}
// SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response.
response.Headers.Remove("transfer-encoding");
using (var responseStream = await responseMessage.Content.ReadAsStreamAsync())
{
await responseStream.CopyToAsync(response.Body, _streamCopyBufferSize, context.RequestAborted);
}
}
And now the preparation is complete. Back to our controller:
private readonly HttpClient _client;
public YourController()
{
_client = new HttpClient(new HttpClientHandler()
{
AllowAutoRedirect = false
});
}
public async Task<IActionResult> Rewrite()
{
var request = HttpContext.CreateProxyHttpRequest(new Uri("https://www.google.com"));
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, HttpContext.RequestAborted);
await HttpContext.CopyProxyHttpResponse(response);
return new EmptyResult();
}
And try to access it. It will be proxied to google.com
A nice reverse proxy middleware implementation can also be found here: https://auth0.com/blog/building-a-reverse-proxy-in-dot-net-core/
Note that I replaced this line here
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
with
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToString());
Original headers (e.g. like an authorization header with a bearer token) would not be added without my modification in my case.
I had luck using twitchax's AspNetCore.Proxy NuGet package, but could not get it to work using the ProxyRoute method shown in twitchax's answer. (Could have easily been a mistake on my end.)
Instead I defined the mapping in Statup.cs Configure() method similar to the code below.
app.UseProxy("api/someexternalapp-proxy/{arg1}", async (args) =>
{
string url = "https://someexternalapp.com/" + args["arg1"];
return await Task.FromResult<string>(url);
});
Piggy-backing on James Lawruk's answer https://stackoverflow.com/a/54149906/6596451 to get the twitchax Proxy attribute to work, I was also getting a 404 error until I specified the full route in the ProxyRoute attribute. I had my static route in a separate controller and the relative path from Controller's route was not working.
This worked:
public class ProxyController : Controller
{
[ProxyRoute("api/Proxy/{name}")]
public static Task<string> Get(string name)
{
return Task.FromResult($"http://www.google.com/");
}
}
This does not:
[Route("api/[controller]")]
public class ProxyController : Controller
{
[ProxyRoute("{name}")]
public static Task<string> Get(string name)
{
return Task.FromResult($"http://www.google.com/");
}
}
Hope this helps someone!
Twitchax's answer seems to be the best solution at the moment. In researching this, I found that Microsoft is developing a more robust solution that fits the exact problem the OP was trying to solve.
Repo: https://github.com/microsoft/reverse-proxy
Article for Preview 1 (they actually just released prev 2): https://devblogs.microsoft.com/dotnet/introducing-yarp-preview-1/
From the Article...
YARP is a project to create a reverse proxy server. It started when we noticed a pattern of questions from internal teams at Microsoft who were either building a reverse proxy for their service or had been asking about APIs and technology for building one, so we decided to get them all together to work on a common solution, which has become YARP.
YARP is a reverse proxy toolkit for building fast proxy servers in .NET using the infrastructure from ASP.NET and .NET. The key differentiator for YARP is that it is being designed to be easily customized and tweaked to match the specific needs of each deployment scenario. YARP plugs into the ASP.NET pipeline for handling incoming requests, and then has its own sub-pipeline for performing the steps to proxy the requests to backend servers. Customers can add additional modules, or replace stock modules as needed.
...
YARP works with either .NET Core 3.1 or .NET 5 preview 4 (or later). Download the preview 4 (or greater) of .NET 5 SDK from https://dotnet.microsoft.com/download/dotnet/5.0
More specifically, one of their sample apps implements authentication (as for the OP's original intent)
https://github.com/microsoft/reverse-proxy/blob/master/samples/ReverseProxy.Auth.Sample/Startup.cs
Here is a basic implementation of Proxy library for ASP.NET Core:
This does not implement the authorization but could be useful to someone looking for a simple reverse proxy with ASP.NET Core. We only use this for development stages.
using System;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
namespace Sample.Proxy
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging(options =>
{
options.AddDebug();
options.AddConsole(console =>
{
console.IncludeScopes = true;
});
});
services.AddProxy(options =>
{
options.MessageHandler = new HttpClientHandler
{
AllowAutoRedirect = false,
UseCookies = true
};
options.PrepareRequest = (originalRequest, message) =>
{
var host = GetHeaderValue(originalRequest, "X-Forwarded-Host") ?? originalRequest.Host.Host;
var port = GetHeaderValue(originalRequest, "X-Forwarded-Port") ?? originalRequest.Host.Port.Value.ToString(CultureInfo.InvariantCulture);
var prefix = GetHeaderValue(originalRequest, "X-Forwarded-Prefix") ?? originalRequest.PathBase;
message.Headers.Add("X-Forwarded-Host", host);
if (!string.IsNullOrWhiteSpace(port)) message.Headers.Add("X-Forwarded-Port", port);
if (!string.IsNullOrWhiteSpace(prefix)) message.Headers.Add("X-Forwarded-Prefix", prefix);
return Task.FromResult(0);
};
});
}
private static string GetHeaderValue(HttpRequest request, string headerName)
{
return request.Headers.TryGetValue(headerName, out StringValues list) ? list.FirstOrDefault() : null;
}
public void Configure(IApplicationBuilder app)
{
app.UseWebSockets()
.Map("/api", api => api.RunProxy(new Uri("http://localhost:8833")))
.Map("/image", api => api.RunProxy(new Uri("http://localhost:8844")))
.Map("/admin", api => api.RunProxy(new Uri("http://localhost:8822")))
.RunProxy(new Uri("http://localhost:8811"));
}
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
We are trying to communicate with a REST server, which uses its own OAuth2 implementation.
This server is written by another company in Java, so I don't have much influence about it.
I've got all the necessary information, like Access Token URL, Refresh URL, Client Id, Client Secret, etc. I can already request an access token and then request some other data from this server, using the REST client Postman.
Now I'd like to use the ServiceStack client (version 4.5.14), to communicate with this server in C# .NET 4.6.2.
My problem is: All the examples I found, e.g. http://docs.servicestack.net/authentication-and-authorization#custom-authentication-and-authorization are either about the server-side or about authentication against Facebook or Google.
I already implemented my own CustomOAuth2Provider, setting the access token URL, ConsumerSecret, etc.
But how do I tell the JsonServiceClient, to use this Provider, before executing the specific request?
Thank you,
Daniel
Edit:
I read a lot of documentation and ServiceStack sourcecode, and I think my main problems are the following:
I abuse the ServiceStack Client to communicate with a non-ServiceStack application, which I can not modify.
Maybe the OAuth2 implementation of the third-party application is not 100% correct, as it expects authorization and token request in the same request.
But I got it working now and would like to show my solution here.
It still can be improved, e.g. it does not use the received refresh token right now.
public class ThirdPartyAuthenticator : IDisposable
{
// TODO: Move to config
public const string AccessTokenUrl = "";
public const string ConsumerKey = "";
public const string ConsumerSecret = "";
public const string Username = "";
public const string Password = "";
/// <summary>
/// Remember the last response, instance comprehensive so we do not need a new token for every request
/// </summary>
public static ServiceModel.ThirdPartyOAuth2Response LastOAuthResponse = null;
/// <summary>
/// This already authenticated client can be used for the data requests.
/// </summary>
public JsonServiceClient AuthenticatedServiceClient { get; set; }
public ThirdPartyAuthenticator()
{
if (LastOAuthResponse == null || (LastOAuthResponse.ExpiryDateTime < DateTime.Now)) // TODO: Use Refresh token?
{
// Get token first
JsonServiceClient authClient = new JsonServiceClient(AccessTokenUrl);
authClient.UserName = ConsumerKey;
authClient.Password = ConsumerSecret;
authClient.AlwaysSendBasicAuthHeader = true;
var request = new ServiceModel.ThirdPartyOAuth2Request();
request.Username = Username;
request.Password = Password;
// Use the Get URI, because server expects username + password as query parameter
LastOAuthResponse = authClient.Post<ServiceModel.ThirdPartyOAuth2Response>(request.ToGetUrl(), request);
}
// If no exception was thrown, we have a valid token here.
AuthenticatedServiceClient = new JsonServiceClient(AccessTokenUrl);
AuthenticatedServiceClient.BearerToken = LastOAuthResponse.AccessToken;
}
public void Dispose()
{
AuthenticatedServiceClient?.Dispose();
}
}
usage:
using (var foo = new ThirdPartyAuthenticator())
{
var response = foo.AuthenticatedServiceClient.Get(new ServiceModel.GetMyData() { SomeId = 10 });
}
OAuth providers require a browser to redirect to the OAuth provider site where Users are able to accept authentication with the App and any permissions it requires. Once the user accepts they're redirected back to your ServiceStack App where it will create an Authenticated User Session. The session id from the Authenticated User Session is what's configured on the ServiceStack client to establish authenticated requests.
Here are some Example Apps which use OAuth to Authenticate using a browser then capture the browser redirect to extract the session cookies and configure it on the C# Service Client where they're then able to make Authenticated requests:
https://github.com/ServiceStackApps/TechStacksAuth
https://github.com/ServiceStackApps/AndroidJavaChat
I made BasicAuth and WindowsAuth work in my SignalR project.
Now I am looking for other ways of authenticating (without needing a Win/AD Account).
While reading the SignalR documentation I stumbled upon the possibility to provide auth tokens in the connection header:
http://www.asp.net/signalr/overview/security/hub-authorization#header
It states "Then, in the hub, you would verify the user's token."
I could make the OnConnected method to be access anonymously and get the token like the following and then verifying it:
var test = Context.Request.Headers["mytoken"];
But what would would be the next step? I would need to set the connected user to be an authenticated user but how can I do that manually?
My overall goal is to have a very simple method of authentication,i.e. a "hardcoded" token validated on the server side and grant access to the other methods which have authorization enabled.
Any help would be appreciated.
I have had a similar problem. I found a kind of workaround creating a new AuthorizeAttribute. Next, I decorated the methods with this attribute. When a request is made, the attribute checks the token and gives the permission or not to be accessed.
Here is the code:
[AttributeUsage(AttributeTargets.Method)]
internal class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubMethodInvocation(Microsoft.AspNet.SignalR.Hubs.IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
string token = hubIncomingInvokerContext.Hub.Context.Headers["AuthenticationToken"];
if (string.IsNullOrEmpty(token))
return false;
else
{
string decryptedValue = Encryptor.Decrypt(token, Encryptor.Password);
string[] values = decryptedValue.Split(';');
string userName = values[0],
deviceId = values[1],
connectionId = values[2];
bool b = ...CanAccess()...;
return b;
}
}
}
To have a username, you can simply add a property in your Hub that reads the token, parse it and returns the username.
Still can't use Context.User.Identity, though. I hope it helps.
I want to send some data to my mvc4 website from my wpf app and received data back from the website back to my wpf application. I tried to find a solution before coming here and people were saying something about a web service should be able to do that, but I dont know if i need to make a web service in my mvc4 website or if I need to make a wcf project in my wpf app.
Any guides or tutorials about this would be greatly appreciated.
EDIT:This is what I ended up with after seeing the first solution it does not work at the moment, I am not sure why im not getting a proper response back.
public bool GetData(LoginObj loginObj)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:12611/");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsJsonAsync("Home/VerifyLogin",loginObj).Result;
if (response.IsSuccessStatusCode)
{
var users = response.Content;
if (users.ToString() == "true")
return true;
else
return false;
}
return false;
}
this is in the home controller below
public class LoginObj
{
public string username { get; set; }
public string password { get; set; }
public LoginObj(string username, string password)
{
this.username = username;
this.password = password;
}
}
public JsonResult VerifyLogin(LoginObj loginObj)
{
bool isValid = true;
isValid = System.Web.Security.Membership.ValidateUser(loginObj.username, loginObj.password);
return Json(isValid,JsonRequestBehavior.AllowGet);
}
I'm not sure what you are trying to do, but normally a web application (mvc4) calls the service. Whatever to send, receive or both.
There you have your web app call the wcf requesting data and if it's changed elsewhere it will be returned from the wcf no matter what. When you need to save data you just send it to the wcf.
If you need some notification/chat-like app so a WCF can push data to your web app, seems like you are looking for SignalR.
If you can, please expand or explain better your question/need.
UPDATE:
You can create a 'web service' (wcf or webapi) or using the already mvc application and return a json response to act like a web service.
The simple you can get is something like :
A new action in your mvc app
public JsonResult CanLogin(string username, string password){
bool isValid = true; // check if username & password are ok and return True or False
return Json(isValid);
}
then on your wpf create an httpclient and call /application/CanLogin with user and password
you can allowGet on the json response for testing in your browser.
return Json(isValid, JsonRequestBehavior.AllowGet);
I am trying again to login to instagram, but i have to do this without using their api v2 which uses oAuth for verifying.
The only thing i have is Username and Password to login.
So what i did was looked for the way, instagram application for Android and hopefully IOS does that.
I see that it creates a request at the following url:
https://instagr.am/api/v1/accounts/login/
If you would visit that link directly, you will more likely get a error saying that the page couldn't be find. After a little bit of googling, i came across a 2 years old post which states that in the Useragent, we have to contain the string "Instagram" for it to work.
I did that by faking the useragent and the result is as follows:
{"status":"fail","message":"Your version of Instagram is out of date. Please upgrade your app in the Play Store to log in to Instagram."}
Now, i am guessing that we also need to add something else or some other headers too, so i was looking for a way to grab the request being sended to instagram by either of their Android or IOS app.
So next i downloaded Bluestack and installed and ran instagram on my computer using this. I was able to install and login it successfully, but then i was unable to log it using Charles since the request is being sent to https:// server
I also tried to grab it through Wireshark but unfortuantely, i am not much experienced in using it and hence don't know it purpose.
So could anyone help me to get how to login to instagram with C# without using oAuth, cuz i just have username and password.
I would probably code the end part of requesting myself, but i am unable to capture the headers being sent to instagram.
Also, if there is anything like Charles/Wireshark which captures network traffic for Android, do let me know about it too.
You should be able to capture the request and see the request headers using Fiddler if you can tell your device to use your pcs internet connection by going through USB. It seems your getting close but might just need a version number somewhere in your request.
Yeah you can do this using Webview
Here you go
mWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
UrlQuerySanitizer.ValueSanitizer sanitizer = UrlQuerySanitizer.getAllButNulLegal();
// remember to decide if you want the first or last parameter with the same name
// If you want the first call setPreferFirstRepeatedParameter(true);
sanitizer.sanitize(url);
String value = sanitizer.sanitize("username"); // get your value
if(MyBridge.getUsername()!=null)username = MyBridge.getUsername();
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
// showLoading();
CookieManager.getInstance().removeAllCookies(null);
// CookieManager.getInstance().flush();
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
if (url.equalsIgnoreCase(mURL)) {
view.addJavascriptInterface(new MyBridge(InstagramOfficalLoginActivity.this), "bridge");
String javascript = "javascript: document.getElementsByClassName(\"_0mzm- sqdOP L3NKy \")[0].onclick = function() {\n" +
" var username = document.getElementsByName(\"username\").value;\n" +
" var password = document.getElementsByName(\"password\").value;\n" +
" bridge.saveData(username, password);\n" +
" };";
view.loadUrl(javascript);
}
if (isSessionid ) {
// username = MyBridge.getUsername();
//сохранение данных пользователя
Logins logins = new Logins();
logins.setUserId(InstaUtils.getUserId());
logins.setUserName("");
logins.setProfilePic("");
logins.setSession_id(InstaUtils.getSessionid());
logins.setCooki(InstaUtils.getCookies());
logins.setCsrf(InstaUtils.getCsrf());
long id = DataObjectRepositry.dataObjectRepositry.addNewUser(logins);
PreferencesManager.savePref(GlobalConstant.USERNAME,username);
PreferencesManager.savePref(GlobalConstant.USER_ID, InstaUtils.getUserId());
PreferencesManager.savePref(GlobalConstant.TOKEN, InstaUtils.getSessionid());
PreferencesManager.savePref(GlobalConstant.PROFILE_PIC,"");
Intent intent = new Intent(InstagramOfficalLoginActivity.this, MainActivity.class);
PreferencesManager.savePref("isLogin",true);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("user", InstaUtils.getUserId());
intent.putExtra("database_id",String.valueOf(id));
mWebView.destroy();
mWebView = null;
startActivity(intent);
}
}
#Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
progressBar.setVisibility(View.GONE);
cookies = CookieManager.getInstance().getCookie(url);
try {
String session_id = getCookie(url, "sessionid");
String csrftoken = getCookie(url, "csrftoken");
String userid = getCookie(url, "ds_user_id");
if (session_id != null && csrftoken != null && userid != null) {
isSessionid = true;
InstaUtils.setSessionId(session_id);
InstaUtils.setUserId(userid);
InstaUtils.setCookies(cookies);
InstaUtils.setCsrf(csrftoken, cookies);
}
}catch (Exception e){
e.printStackTrace();
}
}
#SuppressWarnings("deprecation")
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
ToastUtils.ErrorToast(InstagramOfficalLoginActivity.this, description);
}
#TargetApi(android.os.Build.VERSION_CODES.M)
#Override
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
// Redirect to deprecated method, so you can use it in all SDK versions
onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
}
});
mWebView.loadUrl(mURL);
You can also download fully working code from my github profile Here is the link.
I hope it work,Thanks :)
you can always login through https://instagram.com/accounts/login/ having only login\password.
having ability to sniff traffic will not help you, as they sign all their messages now to prevent things you are trying to achieve.
You can find Instaguser library at here. https://github.com/ThinhVu/InstagramUser
Instaguser allow you login into instagram without OAuth.
At the moment, you can change user information: username, biography, ... etc.