how to add claims in jwt using jose-jwt - c#

i am using jose jwt library to creating jwt token, i am not sure how i can i use the claims tag in the payload. i want to store user name and some other data related to it. below is the code which i am using to generate code
byte[] secretKey = Base64UrlDecode("-----BEGIN PRIVATE KEY-----");
DateTime issued = DateTime.Now;
DateTime expire = DateTime.Now.AddHours(10);
var payload = new Dictionary<string, object>()
{
{"iss", "service email"},
{"aud", "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"},
{"sub", "service email"},
{"iat", ToUnixTime(issued).ToString()},
{"exp", ToUnixTime(expire).ToString()}
};
string token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256);
return token;

The JWT specification talks about three types of claims: Registered, Public and Private.
Registered
The usual ones such as iss, sub, exp, etc.
Public claims
The IANA JWT Claims Registry is used to specify the claims that should be used publicly to standardize them between services. These contains lots of useful ones such as name, email, address, etc.
Private claims
If you are only using your token within your own application or between known applications you could actually add whatever claims you want.
It might be a good idea to avoid using claims from the IANA JWT Claims Registry for other purposes though (ie don't use name to store the users username).
So in your case your code could simply be like this to add the username (with the claim from the IANA registry)
byte[] secretKey = Base64UrlDecode("-----BEGIN PRIVATE KEY-----");
DateTime issued = DateTime.Now;
DateTime expire = DateTime.Now.AddHours(10);
var payload = new Dictionary<string, object>()
{
{"iss", "service email"},
{"aud", "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"},
{"sub", "service email"},
{"iat", ToUnixTime(issued).ToString()},
{"exp", ToUnixTime(expire).ToString()},
{"preferred_username", "MyAwesomeUsername"}
};
string token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256);
return token;
Though if it's only for internal use I would probably go with just username or usr myself.
Another thing to remember (and that many get wrong) is that JWT isn't encrypting anything. The content is base64 encoded but anyone that get hold of your token can read everything in it. So make sure to not put anything sensitive in them if there is even a slight chance that a user can see them.

Related

JWT TOKEN Generate Client_Assertion

I am newbie in JWT access Token generation. I have Public Key, Private key and ClientID. I need to generate Client_Assertion.
client_assertion: JWT (signed by client ID, public certificate and private key using
RS256 as the signature algorithm).
I have found some Node.JS code but I want to do it using .Net Framework (Not .Net Core)
Node.Js code can be seen on this link
I need to do it in C#. From where to start and how to achieve it?
I used the .NET libraries
System.IdentityModel.Tokens.Jwt
Microsoft.IdentityModel.Tokens
Microsoft.IdentityModel.JsonWebTokens
I'm also assuming that, as you said you have a private key, and that you've loaded that into an RSACryptoServiceProvider
Here's my sample code
First create your claims. This is your JWT payload
var claims = new Claim[]
{
new Claim(MicrosoftJwt.JwtRegisteredClaimNames.Sub, "your subject"),
new Claim(MicrosoftJwt.JwtRegisteredClaimNames.Iat, DateTime.Now.ToEpochSeconds().ToString(), ClaimValueTypes.Integer),
new Claim(MicrosoftJwt.JwtRegisteredClaimNames.Exp, DateTime.Now.AddMinutes(60).ToEpochSeconds().ToString(), ClaimValueTypes.Integer),
};
Then you need to configure your signing credentials using your private key.
// Assuming you already have your key loaded into an RSACryptoServiceProvider
var key = new MicrosoftTokens.RsaSecurityKey(csp)
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);
Now you can create your token
var jwt = new JwtSecurityToken(
issuer : issuer,
audience : audience,
claims : claims,
signingCredentials: signingCredentials
);
// You can add extra items to your Header if necessary
jwt.Header.Add("kid", deviceId);
You can then write your token to a string
var assertion = new JwtSecurityTokenHandler().WriteToken(jwt);
I think the value of assertion is what you're trying to get

Differences between AspNetUserToken and custom made JWT token in .NET Core 3.0

I'm working on a small side-project API and I wanted to implement JWT authentication. I already made some API with JWT and always made custom implementation and validation.
This time, I wanted to use Identity/Entity Framework to go faster and to use the tools that are already made for me.
While doing the GenerateToken method and looking through the internet, I noticed that a lot of the tables created by IdentityFramework are not used. And I got interested in AspNetUserToken.
I noticed that instead of
private object GenerateToken(IdentityUser user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(ApiConfig.JwtSecretKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Email, user.Email),
}),
Expires = DateTime.UtcNow.AddSeconds(double.Parse(ApiConfig.JwtExp)), //TODO: Try parse
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Audience = ApiConfig.JwtAudience,
Issuer = ApiConfig.JwtIssuer
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
Which I used to generate a new JWT token, add the claims, issuer, audience, etc... Could maybe be replaced by this :
//Removes existing token
_userManager.RemoveAuthenticationTokenAsync(user, "lboard", "login");
//Creates a new one
var newToken = await _userManager.GenerateUserTokenAsync(user, "lboard", "login");
//Set the new token for the user
await _userManager.SetAuthenticationTokenAsync(user, "lboard", "login", newToken);
I would like to know what are the differences between the two methods, and if there are any benefits of using a custom implementation or if I'm better off with the IdentityFramework one.
The GenerateUserTokenAsync methods is used internally by other UserManager methods like GenerateChangeEmailTokenAsync, GenerateChangePhoneNumberTokenAsync and so on. REF
In order to use more abstract GenerateUserTokenAsync, you must provide a token provider that actually generates the token. Since you don't have any default token providers for a JWT access token, you would still have to write the logic yourself and register your custom token provider and then you could use the GenerateUserTokenAsync method.
You would still need to write the JWT logic by yourself, incude claims etc, but with an added overhead.

get signature from TokenValidatedContext

I'm using the Microsoft.AspNetCore.Authentication.JwtBearer and System.IdentityModel.Tokens.Jwt packages for my .NET Core project.
When configuring the services I'm adding logic to the OnTokenValidated event.
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
// ... set TokenValidationParameters ...
jwtBearerOptions.Events = new JwtBearerEvents()
{
OnTokenValidated = (tokenValidatedContext) =>
{
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
string tokenWithoutSignature = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
// ... full token from request? ...
}
};
});
Since I know the context only returns me the token without the signature I would like to know how I can
either get the full token with signature
or the signature additionally to add it to the tokenWithoutSignature string
If this is not possible:
I'm generating new tokens this way
public string GenerateAccessToken(IDictionary<string, object> payload)
{
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Convert.FromBase64String("secret from config"));
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
Claims = payload,
Expires = DateTime.Now, // value from config
SigningCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256Signature)
};
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
string token = tokenHandler.WriteToken(securityToken);
return token;
}
Maybe I can either retrieve
the token string without the signature
only the signature
within this method?
If nothing works:
Since I kow a bearer token always contains three parts like
header.payload.signature
I could split the string segments to an array, take the first and second element from the array and create a new string of
firstString + . + secondString
That should give me the token without the signature. Are there any better ideas to cut off the signature from a full token?
Why do I want to achieve this?
This question is based on this one
Security token from TokenValidatedContext from the OnTokenValidated event listener is missing last string segment
I'm working with access and refresh tokens. During validation, I have to compare the token from the request with the token from the database. The token in the database contains the signature too. So I'm facing the same problem as linked above.
That's why I thought about multiple solutions and wrote them down here. If the TokenValidatedContext is not able to return me the signature it seems I have to store the JWT to the database without the signature. And also for this case, I need to separate the signature from the generated JWT.
Without using refresh tokens I only store the maximum session lifetime of a user to the database. The flow is based on this idea
Only store the time of the JWT with the highest lifetime to the database instead of the whole JWT
With using refresh tokens I came up with the following flow. Since you know that the OnTokenValidated handles the validation logic the following logic is additional. I have a database table with
username | access_token | refresh_token | refresh_token_expires_at
and the primary key is a composite key of username + access_token. Refresh tokens are just some random strings generated like so
public string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
}
and that's why I'm storing an additional expiration date to it. It should be able to expire after some time.
Signing in
Store the generated access and refresh token and its expiration time for a user to the database. Either store the full access token or the access token without signature to the database (depends on the solution of this question).
Hitting a protected endpoint
Check if that access token for that user exists in the database.
Hitting the refresh endpoint
Check if the database refresh token has expired. If not, compare this one with the refresh token from the request. If everything is fine, remove the old access and refresh token from the database and store the new generated access and refresh token to the database.
Signing out
Remove that access and its connected refresh token from the database.
I don't quite understand why you do all this, but if all you need is the original token, you can use one of these:
o.Events = new JwtBearerEvents
{
OnTokenValidated = (context) =>
{
var securityToken = (System.IdentityModel.Tokens.Jwt.JwtSecurityToken)context.SecurityToken;
var token = securityToken.RawData; // "ey...."
var tokenHeader = securityToken.RawHeader; // "ey...."
var tokenPayload = securityToken.RawPayload; // "ey...."
var tokenSignatur = securityToken.RawSignature; // "ey...."
var fullBearerHeader = context.Request.Headers["Authorization"]; // "Bearer ey..."
return Task.CompletedTask;
}
};
You probably want to make the code a bit more safe with regards to type casting etc., but it should give you the token.
Why do you want to manipulate the token? If it is just to Validate the token you can use below code.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
//ValidIssuer = Configuration["Issuer"],
//ValidAudience = Configuration["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Key"]))
};
});
and
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}

How can I retrieve a user from a password reset token in ASP.NET Core?

I have an ASP.NET Core 2.1 web application and am adding forgot password functionality. I have looked at several examples, and they seem to take one of two approaches. The first approach is to include either the user id or the user's email in the password reset url along with the password reset token. The second approach is to include only the password reset token in the password reset url and then require the user to enter identifying information (such as email) when attempting to change the password (Binary Intellect example). Is there a way to look up the user given just the password reset token?
My team lead has asked me to pass just the token in the password reset url and then look up the user. My initial research makes me believe that I would have to manually keep record of the user id and token relationship, but am hoping that there's something built in. I have reviewed the ASP.NET Core UserManager documentation, but did not find any methods for retrieving a user for a given token.
Here's some of the example code embedding the user id in the password reset URL (Microsoft Password Recovery Doc):
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
There is a way to get the UserId from the password reset token, but in my opinion it's tricky and a lot of work.
What are the defaults
If you have some codes like the following,
services.AddIdentity<AppUser, AppRole>(options =>
{
...
}
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();
the last line .AddDefaultTokenProviders() adds 4 default token providers, which are used to generate tokens for reset passwords, change email and change phone number options, and for two factor authentication token generation, into the pipeline:
DataProtectorTokenProvider
PhoneNumberTokenProvider
EmailTokenProvider
AuthenticatorTokenProvider
The first one, DataProtectorTokenProvider, is what we're looking for. It uses data protection to serialize/encrypt those tokens.
And within the DataProtectorTokenProvider, its protector is default to the name of "DataProtectorTokenProvider".
How tokens are generated
If you look at GenerateAsync() method inside DataProtectorTokenProvider, you can kind of tell the token consists of:
Utc timestamp of the token creation (DateTimeOffset.UtcNow)
userId
Purpose string
Security stamp, if supported
The generate method concatenates all those, transform them to a byte array, and calls the protector inside to protect/encrypt the payload. Finally the payload is converted to a base 64 string.
How to get User Id
To get the userId from a token, you need to do the reverse engineering:
Convert the token from base 64 string back to the byte array
Call the protector inside to unprotect/decrypt the byte array
Read off the Utc timestamp
Read userId
The tricky part here is how to get the same DataProtector used to generate those token!
How to get the default Data Protector
Since the default DataProtectorTokenProvider is DIed into the pipeline, the only way I can think of to get the same DataProtector is to use the default DataProtectorTokenProvider to create a protector with the same default name, "DataProtectorTokenProvider", used to generate tokens!
public class GetResetPasswordViewModelHandler : IRequestHandler<...>
{
...
private readonly IDataProtector _dataProtector;
public GetResetPasswordViewModelHandler(...,
IDataProtectionProvider dataProtectionProvider)
{
...
_dataProtector = dataProtectionProvider.CreateProtector("DataProtectorTokenProvider");
// OR
// dataProtectionProvider.CreateProtector(new DataProtectionTokenProviderOptions().Name);
}
public async Task<ResetPasswordViewModel> Handle(GetResetPasswordViewModel query, ...)
{
// The password reset token comes from query.ResetToken
var resetTokenArray = Convert.FromBase64String(query.ResetToken);
var unprotectedResetTokenArray = _dataProtector.Unprotect(resetTokenArray);
using (var ms = new MemoryStream(unprotectedResetTokenArray))
{
using (var reader = new BinaryReader(ms))
{
// Read off the creation UTC timestamp
reader.ReadInt64();
// Then you can read the userId!
var userId = reader.ReadString();
...
}
}
...
}
}
Screenshot:
My 2 cents
It seems like it's a lot of work just try to read the userId off a password reset token. I understand your team lead probably doesn't want to expose the user id on the password reset link, or (s)he thinks it's redundant since the reset token has the userId.
If you're using integer to represent the userId and don't want to expose that to public, I would change it to GUID.
If you have to use integer as your userId, I would just create a column of the type unique_identifier off the user profile (I would call it PublicToken) and use that to identifier a user for all public matters.
var callbackUrl = Url.Action("resetPassword", "account", new
{
area = "",
rt = passwordResetToken, // reset token
ut = appUser.Id // user token, use GUID user id or appUser.PublicToken
}, protocol: Request.Scheme);
I believe there is no way you can do that you can pass user email then find it look for user in your code
public async Task<IActionResult> ResetPassword([FromBody]ResetPasswordViewModel model)
{
if (string.IsNullOrEmpty(model.Token) || string.IsNullOrEmpty(model.Email))
{
return RedirectToAction("Index", "Error", new { statusCode = AppStatusCode.NotFound });
}
var isResetTokenValid = await _userManager.CheckValidResetPasswordToken(model.Token, model.Email);
if (!isResetTokenValid || string.IsNullOrEmpty(model.Email))
{
return StatusCode(AppStatusCode.ResetPassTokenExpire);
}
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null)
{
return Ok();
}
await _userManager.ResetPasswordAsync(user, model.Token, model.Password);
return Ok();
}
You can view the implementaion detail here
What I do in this case is I keep that new token in a cache or sql table with user id in it. That way you first query that table containing reset token, validate it if you need it and get user.

Return JWT Token generated by OAuthAuthorizatioServer from controller in Web API

Following #Taiseer Joudeh I was able to create simple POC of Web API. I'm able to create new account, then log-in and call secure Web API when I add JWT token to header.
I'd like to modify method that is responsible for creating accounts.
Right now I'm returning Create (201) code with new user object, but instead I'd like to return access token.
I've found similar question but it requires creating HttpClient and doing request to OAuthAuthorizatioServer TokenEndpointPath.
Second question I found requires generating temporary token that is returned to front-end, but then front-end must do additional request to server to get "real" token.
What I'd like to do is to return login response (access_token, token_type and expires_in) when I create user account.
I want user to be authenticated when his account is created.
I'm using just Web API and JWT without any cookies.
EDIT: My temporary solution:
after creating user I'm doing this:
var validTime = new TimeSpan(0, 0, 0, 10);
var identity = await UserManager.CreateIdentityAsync(user, "JWT");
var jwtFormat = new CustomJwtFormat(ApplicationConfiguration.Issuer);
var authenticationProperties = new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow, ExpiresUtc = DateTimeOffset.UtcNow.Add(validTime) };
var authenticationTicket = new AuthenticationTicket(identity, authenticationProperties);
var token = jwtFormat.Protect(authenticationTicket);
var response = new
{
access_token = token,
token_type = "bearer",
expires_in = validTime.TotalSeconds.ToInt()
};
return Ok(response);
where CustomJwtFormat comes from this awesome article.
Below is some code similar to what I'm doing in my application, which is using Asp.Net Core 1.0. Your signin and user registration will differ if you're not using Core 1.0.
public async Task<string> CreateUser(string username, string password)
{
string jwt = String.Empty;
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
var user = await _userManager.FindByNameAsync(username);
if (user == null) // user doesn't exist, create user
{
var newUser = await _userManager.CreateAsync(new ApplicationUser() { UserName = username }, password);
if (newUser.Succeeded) //user was successfully created, sign in user
{
user = await _userManager.FindByNameAsync(username);
var signInResult = await _signInManager.PasswordSignInAsync(user, password, false, true);
if (signInResult.Succeeded) //user signed in, create a JWT
{
var tokenHandler = new JwtSecurityTokenHandler();
List<Claim> userClaims = new List<Claim>();
//add any claims to the userClaims collection that you want to be part of the JWT
//...
ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(user.UserName, "TokenAuth"), userClaims);
DateTime expires = DateTime.Now.AddMinutes(30); //or whatever
var securityToken = tokenHandler.CreateToken(
issuer: _tokenOptions.Issuer, //_tokenAuthOptions is a class that holds the issuer, audience, and RSA security key
audience: _tokenOptions.Audience,
subject: identity,
notBefore: DateTime.Now,
expires: expires,
signingCredentials: _tokenOptions.SigningCredentials
);
jwt = tokenHandler.WriteToken(securityToken);
Response.StatusCode = (int)HttpStatusCode.Created;
await _signInManager.SignOutAsync(); //sign the user out, which deletes the cookie that gets added if you are using Identity. It's not needed as security is based on the JWT
}
}
//handle other cases...
}
}
Basically, the user is created and then signed in automatically. I then build a JWT (add in any claims you want) and return it in the response body. On the client side (MVC and Angular JS) I get the JWT out of the response body and store it. It is then passed back to the server in the Authorization header of each subsequent request. Authorization policies for all server actions are based on the set of claims supplied by the JWT. No cookies, no state on the server.
EDIT: I suppose you don't even need to call the signIn method in this process as you can just create the user, create a JWT, and return the JWT. When a user logs in on a future request you would use the Sign-In, create token, Sign-Out approach.
The idea of sending a response with access_token, token_type and expires_in, when the user is created is a great idea. But, I would stick to calling the "/token" end point with HttpClient to achieve this task. There are quite a few security checks that needs to be performed before token is generated. Since this is security I would not take any risk. I feel comfortable using the libraries/ code provided by industry experts.
That said, I tried to come up with a class you can call to create the token once the user is created. This code has been taken from the Microsoft's implementation of OAuth Authorization Server in their Katana project. You can access the source here. As you can see there is quite a lot happening when creating the token.
Here is the modified version of that middleware class for generating the token. You have to provide the proper OAuthAuthorizationServerOptions, Context, username, password, Scopes and clientid to get an access token. Please note that this is a sample implementation to guide you in the right direction. Please test it thoroughly if you want to use this.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AspNetIdentity.WebApi.Providers;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Microsoft.Owin.Security.OAuth;
namespace WebApi.AccessToken
{
public class TokenGenerator
{
public string ClientId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public IList<string> Scope { get; set; }
private OAuthAuthorizationServerOptions Options { get; } =
new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat("http://localhost:59822")
};
public async Task<IList<KeyValuePair<string, string>>> InvokeTokenEndpointAsync(IOwinContext owinContext)
{
var result = new List<KeyValuePair<string, string>>();
DateTimeOffset currentUtc = Options.SystemClock.UtcNow;
// remove milliseconds in case they don't round-trip
currentUtc = currentUtc.Subtract(TimeSpan.FromMilliseconds(currentUtc.Millisecond));
AuthenticationTicket ticket = await InvokeTokenEndpointResourceOwnerPasswordCredentialsGrantAsync(owinContext, Options, currentUtc);
if (ticket == null)
{
result.Add(new KeyValuePair<string, string>("ERROR", "Failed to create acess_token"));
return result;
}
ticket.Properties.IssuedUtc = currentUtc;
ticket.Properties.ExpiresUtc = currentUtc.Add(Options.AccessTokenExpireTimeSpan);
ticket = new AuthenticationTicket(ticket.Identity, ticket.Properties);
var accessTokenContext = new AuthenticationTokenCreateContext(
owinContext,
Options.AccessTokenFormat,
ticket);
await Options.AccessTokenProvider.CreateAsync(accessTokenContext);
string accessToken = accessTokenContext.Token;
if (string.IsNullOrEmpty(accessToken))
{
accessToken = accessTokenContext.SerializeTicket();
}
DateTimeOffset? accessTokenExpiresUtc = ticket.Properties.ExpiresUtc;
result.Add(new KeyValuePair<string, string>("access_token", accessToken));
result.Add(new KeyValuePair<string, string>("token_type", "bearer"));
TimeSpan? expiresTimeSpan = accessTokenExpiresUtc - currentUtc;
var expiresIn = (long)expiresTimeSpan.Value.TotalSeconds;
if (expiresIn > 0)
{
result.Add(new KeyValuePair<string, string>("expires_in", "bearer"));
}
return result;
}
private async Task<AuthenticationTicket> InvokeTokenEndpointResourceOwnerPasswordCredentialsGrantAsync(IOwinContext owinContext, OAuthAuthorizationServerOptions options, DateTimeOffset currentUtc)
{
var grantContext = new OAuthGrantResourceOwnerCredentialsContext(
owinContext,
options,
ClientId,
UserName,
Password,
Scope);
await options.Provider.GrantResourceOwnerCredentials(grantContext);
return grantContext.Ticket;
}
}
}
Please let me know if you have any questions.
Thank you,
Soma.
I assume you are referring to the following article: http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/
The general approach to authenticating a user in this case is
Make an HTTP call to the token endpoint
User Enters the credentials at the UI that is rendered
IdP verifies the credentials and issues a token
User makes another call to an authorized endpoint and OWIN will validate this (JWT) token (as configured in the ConfigureOAuthTokenConsumption method) and if successfull will set a user session with expiry same as the token expiry. The session is set using session cookies.
Now try to understand that in general, this whole process of authentication is required because your server does not trust the user logging in to be the user the person is claiming to be. However, in your case, you (or your server code) just created a user and you know for sure that the person accessing your website is the user you have just created. In this case you don't need to validate a token to create a session for this user. Just create a session with an expiry that suits your use-case.
The next time the user will have to log-in and prove him/herself to the server using a token but this time the user does not need to prove him/her self.
Note: If you absolutely are adamant about requiring a token to log in a user who you yourself have just created using their credentials here are a couple of issues.
You are taking on the responsibility of storing (having access to) the user credentials, which might not be with you over the lifetime of the application (in most cases you might want to act as a relying party rather than an IdP).
Even if you want to then doing it is not trivial. You will have to make the calls to the token end point in code (server or client side) on behalf of the user, enter their credentials for them, retrieve the token, call an authenticated endpoint on your site and retrieve the session cookie all while hiding all this from the user, which probably is something you will either do if you hate yourself :) but also isn't very secure way of doing things especially when you are taking all the trouble to implement OAuth in the first place.
Also, take a look at Windows Server 2016 (technical preview 5 at this time) which supports implicit grants and might take writing all this custom code off your plate if you can wait a bit for RTM.
In an OAuth solution you as a developer are are not required to handle the cookie setting yourself. The cookie handling is done for you automatically by the framework.
Also the only way to set a session is a. Using session cookies or b. Use cookie-less (in the url) methods. Look at http://www.cloudidentity.com/blog/2015/02/19/introducing-adal-js-v1/ for more details on token validation and session establishment (also search the term cookie and you will know what all it's used for).
If you start thinking about not using cookies at all not only will you have to figure out how to maintain session and do it securely without cookies but also have to re-write the token refresh code that detects and refreshes the token for you based on the presence of a session cookie. (i.e. not a smart idea)
I am using the exact technology stack and recently implemented token based authorization successfully. The link I took reference from had very neatly defined the token-based auth in Web APIs. A must bookmark page I must say. Here is the link: TOKEN BASED AUTHENTICATION IN WEB APIs.

Categories