How are users authenticated and retrieved? - asp.net-web-api

Having worked my way through this tutorial:
http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/
I now have the solution standing upright and I can issue JWT tokens (what I think of as 'login') and authenticate requests by passing in those tokens during subsequent calls.
What I'm not clear on is how the [Authorize] attribute is:
Recognising a user as authenticated
Retrieving a user from the database
Making that user available to my code
How I would add to the authentication process if I wanted to (perhaps including extra authentication logic after the exiting logic)
[EDIT] I understand that JWT tokens are being used to identify the user but I don't understand 'how' this is taking place. I also understand the middleware is doing it, but the workings of this are not clear.

with the [Authorize] attribute an AuthorizationFilter will added to the filter chain before the controller is called. This article illustrates that.
With the call to ConfigureOAuthTokenConsumption (Step 6 in the tutorial) you give the middleware the information it needs to validate and process tokens.
the authentication, i.e. check username and password, happens only before the token is issued in
public override async Task
GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) {
...
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
...
}
the AuthorizationFilter will only see the token and rely on the information in the token itself
this blog post gives you an example how you can access the username:
var currentPrincipal = ClaimsPrincipal.Current;
string userName = "Anonymous";
if (currentPrincipal.Identity.IsAuthenticated)
{
userName = currentPrincipal.Identity.Name;
}
the middleware gets the information from the token
you can add you own logic either before the token is issued in GrantResourceOwnerCredentials or add your own AuthorizationFilter if you need additonal logic when you receive the token. The blog post linked under 3. shows an example for that.

Related

Add UserType To JWT Token IN laravel

How Can I Bind userType with jwt token??
because in the frontend needs to do some operations with type of user(hide some menus if userType is different)
in laravel.. Does it possible?
The way Laravel (and you most likely using https://github.com/tymondesigns/jwt-auth), is that the JWT should probably not carry user types or really other kind of user information than maybe a name or an id. After the token is generated, you are supposed to query another endpoint that will return the user information that you are looking for.
So essentially, what you want is 2 routes, let's say:
POST /auth/login
POST /auth/me
To the first route, you are supposed to provide the username and password, to which you'll get a token if credentials are correct. Then, you take the token you were just given, and call the second endpoint, which will return all user information you might want or need. You don't specify which kind of frontend you are using, but here's an example with Nuxt.js's Auth module: https://auth.nuxtjs.org/providers/laravel-jwt/

Dynamically changing JWT subject field

I successfully implemented JWT as a authentication filter in my web application. When user's login is successful, I am creating a new JWT and assigning userName in the sub field of JWT.
In the subsequent request's I am using userName in the JWT sub field to identify the user. But what if the user changes his userName in the update section of the application. Is there way, I can update the value of sub field in JWT ?
What I am thinking!
I am thinking of getting the existing JWT in the RestController and after updating the userName, I will update the JWT with new userName and again send back to the client. Is this fine or is there a better approach?
I think I should refresh the token after update is done and send back the refreshed token back to client.
#RequestMapping( value = "/account", method = RequestMethod.POST )
public ResponseEntity<?> updateAccount( #RequestBody UserDetailsBean userDetailsBean, HttpServletRequest request,
HttpServletResponse response )
{
try
{
UserAccessDetails accessDetails = getLoggedInUser();
UserDetailsBean updatedUserBean = userService.updateAccount(userDetailsBean, accessDetails);
// send updated jwt incase of mobile number update by user
response.addHeader(SecurityConstants.HEADER_STRING,
SecurityConstants.TOKEN_PREFIX + refreshJWT(updatedUserBean.getMobileNumber()));
return buildResponse(updatedUserBean);
}
catch( DataException e )
{
return buildError(e);
}
}
private String refreshJWT( String subject )
{
return Jwts.builder().setSubject((subject))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET).compact();
}
This is working. If anyone has a cleaner and industry standard approach please specify.
If you allow your users to change their usernames, they should also have an immutable user id that can be used to identify any data or activity associated with a given user. Otherwise, any time a user changes his or her name, you will either lose the ability to audit the user's past actions or you will have to update all references to that username in the database. What's worse is if there are references to an old username in the database and another user takes that username -- now you have data from one user now being associated with another due to incorrect handling of user identification.
Now with that said, the sub claim should contain this immutable user id. You can create a separate claim for the mutable username. When a username is changed, you now only need to change a single field in the database (assuming that only the users table references this mutable username). You could then use the refresh token retrieve a new token that would contain the latest username that could then be used by your API as needed.
Using this approach, you should be careful to only use the username claim for display purposes, not for identifying the logged in user due to the fact that it is mutable. The sub claim containing the user id would serve the purpose of identifying a user.
It is also important to note that this solution requires no special logic for "updating the sub claim." You would be using the same logic that you're already using to generate a token for a supplied refresh token.

OKTA Session API

Is there an API (we are using the OKTA Sign In Widget) to get the original res.idToken?
Reason I ask is that users might hit our site after logging in to a different site and we need the idToken. We can tell if the session exists of course..
oktaSignIn.session.exists((exists) => {
if (exists) { oktaSignIn.session.get((res) =>
But I don't see an idToken in there.
Thanks!
Can you use tokenManager to store the tokens?
After receiving the id token, you can add it a tokenManager. The token can later be retrieved from there.
Refer - https://github.com/okta/okta-signin-widget#oidc-tokenmanageraddkey-token
Well.. seems like I can get a new IDToken. The docs say this:
oktaSignIn.idToken.refresh(token, function (newToken) {
// New id_token with extended lifetime
});
My problem of course was that I did not have have a token to refresh. Turns out you can just do... (use null instead of a token)
oktaSignIn.idToken.refresh(null, function (newToken) {
// New id_token with extended lifetime
});
Hopefully this is not a bug but a feature :-)

django rest framework - adding to views.obtain_auth_token

I have implemented Token Authentication with django rest framework and I can post username and password to /api-token-auth/ and get the token.
url(r'^api-token-auth/', token_views.obtain_auth_token)
In addition to the token, I want to get the User object related to the returned token.
How can I override/add to this view and also return the actual User object?
You can find the relevant view here:
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/authtoken/views.py#L21
Assuming you've created some sort of User serializer already, you can basically take the user instance there and shove it into your UserSerializer. then add it to the response, something like the below.
...
user_serializer = UserSerializer(user)
return Response({'token': token.key, 'user': user_serializer.data})

Simple Authorization in MVC3 with Forms Authentication

I'm trying to do what should be a simple thing in MVC3.
I've got an application that uses forms authentication to authenticate users with a 3rd party SSO. The SSO, on successful login, posts back to a specific controller action on my application. I then call FormsAuthentication.SetAuthCookie(user,false);.
I'm trying to implement some level of authorization. Simply, a user can exist in a number of different roles, e.g. Admin and Developer. Some controller actions should only be available to certain roles. Details of which roles a user belongs to is obtained by making a call to another external API, which returns a simple JSON response indicating.
In theory, this should be as simple as doing something like this after I set the FormsAuthentication cookie:
string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
HttpContext.User = new GenericPrincipal(User.Identity, rolelist);
However, I can't call this directly after calling SetAuthCookie, because HttpContext.User isn't anything meaningful at this point.
I could try setting this on every request, but ever request to my app would mean a roundtrip API call.
The most promising approach I've seen so far is to create a custom Authorization attribute and override OnAuthorization to do something like this:
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (<some way of checking if roles have already been set for this user, or role cache has timed out>)
{
string[] rolelist = GetRoleListForUserFromAPI(filterContext.HttpContext.User.Identity.Name);
filterContext.HttpContext.User = new GenericPrincipal(filterContext.HttpContext.User.Identity,rolelist);
}
}
I could then use [MyCustomAuthorization(Roles="Admin")] in front of controller actions to make the magic happen.
However, I've no idea how to detect whether or not the current HttpContext.User object has had its roles set, or whether it was set over a certain time ago and another API trip is needed.
What's the best approach for this?
Another way would be to store the roles in the UserData property of the FormsAuthentcationTicket. This could be done with comma delimited string.
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthenticationticket.formsauthenticationticket
Then on AuthenticateRequest method, you could pull the ticket back, grab the roles data and assign it to the current user using a generic principal.
You should override PostAuthenticateRequest
protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
HttpContext.User = new GenericPrincipal(User.Identity, rolelist);
}
}
It's invoked after forms authentication is finished with it's processing.
http://msdn.microsoft.com/en-us/library/ff647070.aspx
Update
I had the wrong method signature (just checked in one of my own applications).
My first thought is that you should investigate implementing a custom role provider. This might be overkill but seems to fit in with the role-based plumbing.
More info from MSDN here.
Much to the aghast of some, the session object ISNT a bad idea here.
If you use temp data, you already take a hit for the session.
Storing this data in the cookie, well - Forms auth tokens have already been exploited in the POET vulnerability from a year and a half ago, so in that case someone could've simply formed their own cookie with the "admin" string in it using that vulnerability.
You can do this in post authenticate as #jgauffin mentioned.
If the session state isn't available there you can use it then in Application_PreRequestHandlerExecute and check it there.
If you want to check if session state is available in either see my code at:
How can I handle forms authentication timeout exceptions in ASP.NET?
Also whenever using forms auth and sessions, you always want to make sure the timeouts are in sync with each other (again the above code)

Resources