MVC 5 Web API Login without Bearer Token - authentication

Long story short. I have a login form in the header on every single page, when I log in successfully it works fine but when the user is incorrect for example it redirects to the default login page (a view that was originally created with MVC project) with the model errors. I don't want to do that, I want to show errors next to the login form without redirecting. So I decided to implement a login via WEB API - i.e. it does $.ajax jQuery request to the Login API Controller, tries to log user in and returns errors if needed so I can output them where I want.
All examples I've seen say to use Bearer Access Token. I don't understand why would I need to go this path - save the token somewhere and pass it along with every single request in the headers? That's what I did in my Login API Controller:
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
Authentication.SignIn(new AuthenticationProperties() { IsPersistent = false }, identity);
}
else
{
error = "Invalid username or password.";
}
This is the same functionality that is available out of the box when you create MVC5 project. I just moved it from regular controller to API controller. And it works without needing to take care of some bearer access tokens. What's the point of it if you could just do it like I did? I think it just makes requests more complicated when you use bearer token. Am I missing anything?

As I understand this, the bearer token would make more sense when you need to have a separately available backend authenticated with the same login as the front end we site in a pass through so the back end can "see" the request as coming from the same user.
You can verify that after logging in this way both the front end web site and backend api are sending the same session cookie, and if so you are golden. If on different domains, you may have problems with that, but otherwise not. If so, then a bearer token to pass that user to the backend may come back into play.

Related

How to pass ui_locales back to requested client?

How can I pass the ui_locales from IdentityServer to clients after the Authorised Request has completed?
I've got multiple apps + Idsv4 under different domains (we can't share cookies). Example:
Mvc App1 (Main landing website)
Mvc App2
Identity Server
The user goes to MvcApp1 and changes the UiLocales on the screen (Eg. es-ES). I stored ui-Culture in the cookies
Then they click login and the AuthorisedRequest is sent to Idsv4 with ui_locales (es-ES).
Idsv4 receives the ui_locales and display the correct translated text (es-ES) with Login screen.
The user enters user credentials, successful and return to redirectUri
App1 can still show the correct text because it stores the locales in the cookies
When User naviagates to App2 and authorize request occurs, Idsv4 doesn't return the correct locales
so, App2 always show English text after successful authorization
The problem is that I can manage to pass the locales information between main app and idsv4 to display correct localized texts in both applications. But when the user navigate to second app (we've got more than 5 apps linked to idsv4), it's always set back to English text.
Please see the sequence diagram below:
As you can see above, since Idsv4 doesn't return ui_locales information (even though it does display correct translation text on its own), second app couldn't detect which language to display and fall back to default language - English.
I passeed the culture info per following in Startup.cs of App1. But ctx.ProtocolMessage.UiLocales is always null on OnAuthorizationCodeReceived event.
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = ctx =>
{
ctx.ProtocolMessage.UiLocales = Thread.CurrentThread.CurrentUICulture.Name;
return Task.CompletedTask;
},
OnAuthorizationCodeReceived = ctx =>
{
Console.WriteLine("OnAuthorizationCodeReceived");
return Task.CompletedTask;
},
....
}
So, I am wondering is there anyway to embed ui_locales values after the successful authorization in Idsv4.
Or Idsv4 is not doing like that because it's not the responsibility of Authentication Service?
Do I have to pass the locale information when the user navigates to other Apps to workaround this problem?
Example: https://ttcgApp1.com/?ui=es-ES, https://MyApp2.net/?ui-es-ES
Could you please help?
IdentityServer does not send any information back to the client, so best solution may be to add a claim that tells which locale was used at the time of login.
Please note that the token does contain additional information about the login process, e.g. the used flow: "amr" = [ "pwd"].
Information that can be used to limit access on the client, e.g. requiring 2FA.
Since OnAuthorizationCodeReceived is only called after succesful login, that's the one place where you can read the claim and use it to set the locale accordingly to the user locale in IdentityServer.

best practices for refreshing access tokens automatically

I'm building a react native app which uses the spotify web api. I'm using the authorization code flow to authorize a user. First I get a authorization code which can be used to obtain an access token and a refresh token. Everything works!
The problem is: an access token is only valid for a limited amount of time. That's where the refresh token comes in. I understand this concept, but I'm breaking my head about how to implement this.
Let's say a users opens the app, requests an access token and uses this for some time. Then, the user closes the app. After 15 minutes, the users opens the app again. The access token has now expired, so I need to request a new access token.
I've come op with several "solutions". Can someone point me to the correct solution?
Solution 1:
Every time the user opens the app, I request a new access token and use this. Problem: when the user uses the app longer than the valid time of the access token, I won't work anymore.
Solution 2:
I use the access token that's stored in the secure storage on every request. When a request comes back with 'access token invalid' (I don't know the exact error code but you guys know what I mean), I request a new access token with the stored refresh token, and then I send the previous command again (with the new access token). But my question here is: can I use some kind of "wrapper function" which checks the response of the request, and if the response is "access token invalid", it automatically requests a new access token and runs the previous request again.
I think certainly correct solution is solution 2,and i think its clear enough.
and for using solution 2 you need somthing like wrapper function,yes its intelligently.
so you should use interceptor:
what is interceptor ?
You can intercept requests or responses before they are handled by then or catch.
in link below there is a good example of implementing refresh token in axios interceptor:
https://gist.github.com/Godofbrowser/bf118322301af3fc334437c683887c5f
I agree that Solution 2 is the best, each time you do a request you can check to see if the Access Token has expired, and if it has then you can request a new Access Token using the Refresh Token as you mentioned and then make your request, in my own project I do this in a FormatRequestHeadersAsync method which calls a CheckAndRenewTokenAsync method where I perform the following check, here shown in C#:
if(AccessToken?.Refresh != null && (AccessToken.Expiration < DateTime.UtcNow))
{
AccessToken = await GetRefreshTokenAsync(
AccessToken.Refresh,
AccessToken.TokenType,
cancellationToken);
}
You can store the Access Token and the Refresh Token and then use something similar to this before you make each request to the API this will refresh your token and then you can store the new Access Token and the existing Refresh Token.

Authentication on Instagram to get the access_token using the API

I'm using the Instagram API and want to get the access_token in order to throw api requests over my own account. When I try to follow the first step and get the authorization code programmatically using RestTemplate I can't get it work.
String AUTHORIZE_URL = "https://api.instagram.com/oauth/authorize/?client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&response_type=code";
String url = String.format(AUTHORIZE_URL, clientId, redirectUri);
String o = restTemplate.getForObject(url, String.class);
The response is the html code of the login page because Instagram requires the user to be logged in to check if the app is authorized (of course it is, since the app an the user belongs to my own account).
How can I authenticate before throwing that request so they return the code to my redirectUri and not complain about login?
Note: I tried simulating the request to their login form but it returned a 403 Forbidden.
NOTE: I already got a valid access_token, manually generated, and it works perfectly but I want to implement also a process to re-generate a new access_token automatically since they may invalidate it at any time in the future.
Even though our access tokens do not specify an expiration time, your app should handle the case that either the user revokes access, or Instagram expires the token after some period of time. If the token is no longer valid, API responses will contain an “error_type=OAuthAccessTokenError”. In this case you will need to re-authenticate the user to obtain a new valid token.
In other words: do not assume your access_token is valid forever.
Instagram is upgrading their APIs and the flows. Earlier we needed access token to bypass forced login screen. Since yesterday, they have removed that.
Now if you call this code, it will check if you are already logged in or not. If so, it will call the AUTHORIZE_URL of yours and will send a response code. The format will be either:
On success validation - http://your-redirect-uri?code=CODE
On error - http://your-redirect-uri?error=access_denied&error_reason=user_denied&error_description=The+user+denied+your+request
Now what I'm doing is I'm directly calling the above URL of yours every time. Now if the user is logged in, a response code will be sent to you, else user will be asked to login and validate your app and then the code will be sent. Technically, you are eliminating the possibility of the error case! So no need of overhead of storing access token in your database or verifying its validity.
Just try and check now what happens.
PS: If you want to check API behavior, simply type the URL on the browser and check what it returns! It helped me a lot while coding and debugging! :)

LinqToTwitter - IsAuthorized always returns false for ApplicationOnlyAuthorizer

I have an MVC4 web application that uses LinqToTwitter to display Tweets when a user's profile page is visited, if they have a Twitter handle.
For this I use ApplicationOnlyAuthorizer:
var auth = new ApplicationOnlyAuthorizer
{
Credentials = new InMemoryCredentials
{
ConsumerKey = "twitterConsumerKey",
ConsumerSecret = "twitterConsumerSecret"
}
};
auth.Authorize();
My problem is that I have found that auth.IsAuthorized always returns false, even when I have call Authorize() and am successfully able to make calls to Twitter. And also, I have found that if I call Authorize() in every call made to Twitter, that an unhandled exception is thrown if I repeat the call enough times.
It seems quite important that I am able to know if auth is authorized before I make the call to Twitter. For now, I have put in a quick fix where I store my own IsAuthorized Session variable - but am not sure how reliable this is, because the Session variable could outlive the actual authentication itself?
Any advice on this would be appreciated.
The first time you authorize, Twitter will return a bearer token. After Authorize, you can grab this from the auth.BearerToken property. On subsequent calls, you can re-use the same bearer token. The bearer token doesn't expire, unless you invalidate it. Twitter's recommendation is that you use the bearer token for about 15 minutes and then re-authorize after that.

Problems configuring user authentication by external API on Symfony2

I have a problem authenticating users for my new Symfony2 application.
This applications gets all the info through an API, so no database is used. When a user goes to login page, he introduce the user and password in the login form. Then, I have to authenticate him using an API call. This API call returns "false" if it's not a user, and return a token key and a token secret if its a correct user. With this token key and secret, during the user session, I can make all the API requests I need for rendering all the pages of the application. Once the user session is over and token key and secret are erased, the user has to login again.
I don't know really how ti implement that. I read this http://symfony.com/doc/current/cookbook/security/custom_provider.html and that http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html, and I'm still so lost... :(
Can any one help me?
Thank you so much :)
If you want to write custom authentication you have found the correct links. As an example you can see the implementation of the OAuth authorization HWIOAuthBundle. But keep in mind that this type of authentication creates a user on your system. If you do not use a database, you must make a request to the API every time user send a request.
First you need to understand that there is no magic. On every request symfony checks if url matches one of the specified firewalls (see secutity.yml). Listener that fired you can see in the firewall factory. If matches are found, the action switches to the corresponding AuthenticationListener. Listener attempts to authenticate the credewntials by creating Token, which is sended to AuthenticationProvider
$this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
in AuthenticationProvider
public function authenticate(TokenInterface $token) {
...
}
AuthenticationProvider try to get user via UserProvider. In case of success, Token stored in the session. On subsequent requests, ContextListener comes into play first, checks the session, extract token and send it to AuthenticationProvider similar.
In general terms, the scheme looks like that. More info you can find examining the source code of Symfony Security component.
Really good starting point is a UsernamePasswordFormAuthenticationListener. It just take login and password from request and make simplest UsernamePasswordToken.
protected function attemptAuthentication(Request $request)
{
...
}
Good luck!