I have token based authentication on WebApi. Token with claims are send to MVC client. Claims are registered like this in WebApi
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("userName", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
I checked the claims and they are registered in web Api, but when MVC request the token, claims are missing.
This is happening in clinet MVC app:
var ctx = Request.GetOwinContext();
var cl2 = ctx.Authentication.User.Claims; // here there is no claims
The same code returns correct claims in WebApi(the server)
I guess I am doing something wrong
Related
I'm working with a .net framework 4.7 app hosted in IIS. The api needs to be secured with JWT token. Identity is provided by another server and clients will send the JWT as bearer token in the header. I like to use OWIN pipeline for authorization. Currently the app uses Global.asax for startup and I like to keep it as is. I just want OWIN for authorization using JWT. I will use the [Authorize] attribute on the controllers needing jwt authorization. IIS doesn't do any authorization at the moment.
I have this in the Startup.cs for Owin.
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = ConfigHelper.GetAudience(),
ValidIssuer = ConfigHelper.GetIssuer(),
ValidateLifetime = true,
ValidateIssuerSigningKey = true
}
});
}
}
How do I call the Startup.Configure() from Global.asax so Owin pipeline handles the authorization for incoming requests.
Thanks
You can have both global.asax and OWIN startup in the same project. ASP.NET will first call the global.asax and hand the control over to OWIN's startup. Make sure you have the Microsoft.Owin.Host.SystemWeb package installed in the project. And you have a class with the name Startup and a method Configuration(IAppBuilder app). There are other ways to let OWIN know where it should start.
You should also be aware of the fact that in .NET framework, there is a manual process to retrieve the signing keys from the authority that issued the JWT token. Otherwise, you will get the mismatched key error. Once you get the keys, you will assign them to ValidSigningKeys property in TokenValidationParameters. Search SO for examples.
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = ConfigHelper.GetAudience(),
ValidIssuer = ConfigHelper.GetIssuer(),
ValidateLifetime = true,
ValidateIssuerSigningKey = true
}
});
}
I need to implement role based authorization for asp .net web api
from native client application the access token will be sent in the header ,
so when i give [Authorize] attribute to my web api it is working fine,but when i give [Authorize(Role="Admin")] it is giving unauthorized error,
then whenever check for role in the claims it is always null.
My startup.cs is
public void Configuration(IAppBuilder app)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
});
}
and i have applied authorize attribute for a method
[Authorize]
[HttpGet]
public async Task<UserDetails> TestAuthorization()
{
string upn = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Name).Value;
string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
var role = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Role);
return null;
}
here the role value is always null
Please help me on this
I'm trying to implement IUserTokenProvider interface to register in Identity system and use further for authentication.
Why token authentication because i write Web Api server in Asp Net Core using Identity 3.
The obstacle is i don't know how to generate token. IUserTokenProvider has 2 method i need: 1. generates token 2. validates token.
what do i write inside them? what's algorithm?
public class UserTokenProvider : IUserTokenProvider<AppUser>
{
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<AppUser> manager, AppUser user)
{
throw new NotImplementedException();
}
public Task<string> GenerateAsync(string purpose, UserManager<AppUser> manager, AppUser user)
{
/* here logic to generate token */
string result = "generated token";
return Task.FromResult(result);
}
public Task<bool> ValidateAsync(string purpose, string token, UserManager<AppUser> manager, AppUser user)
{
/* validating token */
if (token == "generated token")
return Task.FromResult(true);
else return Task.FromResult(false);
}
}
and in ConfigureServices method of StartUp class i register my provider:
services.AddIdentity<AppUser, IdentityRole>(options => {
options.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<UserDbContext>()
.AddTokenProvider<UserTokenProvider>("AuthToken")
.AddDefaultTokenProviders();
As explained in this other SO post, IUserTokenProvider has absolutely nothing to do with token authentication.
I'd recommend reading these other questions for more information about how you can issue your own access tokens in ASP.NET Core:
Simple JWT authentication in ASP.NET Core 1.0 Web API.
Web API Authentication in ASP.NET 5.
Configure the authorization server endpoint.
I am creating a simple authentication server using the default owin oauth server. After supplying the correct credentials a bearer token is generated and returned to the client. I used among others this tutorial by Taiseer
I would like to store the token in a database before the token is send to the client.
Maybe I completely overlooked it, but where can I get the token before it is send? As far as I know the token is generated after the ticket is validated in the GrantResourceOwnerCredentials method.
I am guessing the token is stored in the context. How can I get it out?
Startup.cs
private void ConfigureAuthServer(IAppBuilder app) {
// Configure the application for OAuth based flow
var oAuthServerOptions = new OAuthAuthorizationServerOptions {
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14)
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
ApplicationOAuthProvider
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) {
//Dummy check here
if (context.UserName != context.Password) {
context.SetError("invalid_grant", "The user name or password is incorrect");
return Task.FromResult<object>(null);
}
var claims = new List<Claim> {
new Claim(ClaimTypes.NameIdentifier, context.UserName),
new Claim(ClaimTypes.Name, context.UserName)
};
var oAuthIdentity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
context.Validated(ticket);
return Task.FromResult<object>(null);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context) {
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) {
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
Note: for those who wonder why I want to store the tokens.. it is a requirement I have to fulfill.
To fetch the token before it is sent to the client you must override TokenEndpointResponse:
public override Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
{
return base.TokenEndpointResponse(context);
}
the context object has a property AccessToken which will contains the representation of the token as a string.
OAuthTokenEndpointResponseContext contains a dictionary of objects
IDictionary<string, object> in AdditionalResponseParameters which allows us to find all the claims for the indentity.
If we wanted to fetch the expiration of the token we would find the claim .expires in the dictionary:
context.AdditionalResponseParameters[".expires"]
There's a github repository if someone is interested to play with a simple integration of client and server interaction.
let me first set the stage with the cast of characters:
An MVC 5 application
A WebAPI
I need to implement a token based security to access #2 from #1.
What I have already:
Created a startup class in #2
public void Configuration(IAppBuilder app)
{
// token generation
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(8),
Provider = new MyServerProvider()
});
// token consumption
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
var httpConfiguration = new HttpConfiguration();
WebApiConfig.Register(new HttpConfiguration());
app.UseWebApi(httpConfiguration);
}
Standard code available everywhere on the internet.
This is the code in MyServerProvider also in #2
public class MyServerProvider: OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
await Task.FromResult(0);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (context.UserName == "one" && context.Password == "two")
{
var id = new ClaimsIdentity(context.Options.AuthenticationType);
id.AddClaim(new Claim("name", context.UserName));
id.AddClaim(new Claim("role", "user"));
context.Validated(id);
}
else
{
context.Rejected();
}
await Task.FromResult(0);
}
}
And another class that provides the token also in #3
public class TokenProvider
{
public TokenResponse _tokenValue { get; set; }
public string _accessToken { get; set; }
public string GetToken(string tokenEndpoint, string userName, string password)
{
var client = new OAuth2Client(new Uri(tokenEndpoint));
var tokenResponse = client.RequestResourceOwnerPasswordAsync(userName, userName).Result;
_tokenValue = tokenResponse;
_accessToken = _tokenValue.AccessToken;
return _accessToken;
}
}
So far so good.
Q1. Now when a request from a controller hits the api or the api is
called form JavaScript, what happens?
Q2. Which method from the
above get's called?
Q3. What does GrantResourceOwnerCredentials do?
Q4. What does the context object in the above question has and how
does one add the userName and Password to it and how are claims store in a cookie?
Q5. If I have to store the token in a cookie and use it for subsequent requests, do I write
that code in OnActionExecuting method of the controller in #1?
This all may sound very specific but it isn't. I am trying to understand token based authentication from a real world scenario and I am new to this.
I have gone through the samples at ThinkTecture Github repo and they all do a good job in explaining them but I am stuck at implementing it.
Any help is greatly appreciated.
Regards.