C# Open ID Connect Generate Token from a service class - c#

I have the following code in my Startup.cs
var openIdOptions = new OpenIdConnectAuthenticationOptions
{
ClientId = openIdConfiguration.ClientId,
Authority = openIdConfiguration.Authority,
RedirectUri = openIdConfiguration.RedirectUri,
ResponseType = openIdConfiguration.CodeFlowEnabled ? "code" : OpenIdConnectResponseTypes.IdToken,
TokenValidationParameters = tokenValidationParameters,
Scope = string.IsNullOrEmpty(openIdConfiguration.Scope) ? OpenIdConnectScopes.OpenIdProfile : openIdConfiguration.Scope,
PostLogoutRedirectUri = openIdConfiguration.PostLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = this.AuthorizationCodeReceived,
MessageReceived = this.MessageReceived,
SecurityTokenValidated = this.SecurityTokenValidated,
SecurityTokenReceived = this.SecurityTokenReceived,
AuthenticationFailed = this.AuthenticationFailed,
RedirectToIdentityProvider = this.RedirectToIdentityProvider
},
SignInAsAuthenticationType = "Cookies",
CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
};
....
app.UseOpenIdConnectAuthentication(openIdOptions);
I would like to generate a token from a separate TokenService.cs, with a different configuration which will be consumed by another application.
public class TokenService
{
public async Task<string> GenerateToken()
{
var openIdOptions = new OpenIdConnectAuthenticationOptions
{
//similar OIDC config
}
**// How to generate a token ?**
return token;
}
}
How to go about generating a new token when needed from my TokenService class ?

Related

When using HttpClient with .AddClientAccessTokenHandler() extension, role claim is not included

I am using IdentityModel.AspNetCore and .AddClientAccessTokenHandler() extension to automatically supply HttpClient with access token (at least that is what I understand I can use it for) to an API. Some API endpoints are authorized based on a role. But for some reason, the access token that is added to the request does not contain the role claim. If I do not use the .AddClientAccessTokenHandler() and manually retrieve the token and set it using SetBearerToken(accessTone) then I can reach my role authorized endpoint.
My startup is:
services.AddAccessTokenManagement(options =>
{
options.Client.Clients.Add("auth", new ClientCredentialsTokenRequest
{
Address = "https://localhost:44358/connect/token",
ClientId = "clientId",
ClientSecret = "clientSecret",
});
});
WebApi call:
var response = await _httpClient.GetAsync("api/WeatherForecast/SecretRole");
Identity server configuration:
public static IEnumerable<ApiResource> GetApis() =>
new List<ApiResource>
{
new ApiResource("WebApi", new string[] { "role" })
{ Scopes = { "WebApi.All" }}
};
public static IEnumerable<ApiScope> GetApiScopes() =>
new List<ApiScope>
{ new ApiScope("WebApi.All") };
public static IEnumerable<IdentityResource> GetIdentityResources() =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource
{
Name = "roles",
UserClaims = { "role" }
}
};
public static IEnumerable<Client> GetClients() =>
new List<Client>
{
new Client
{
ClientId = "clientId",
ClientSecrets = { new Secret("clientSecret".ToSha256()) },
AllowedGrantTypes =
{
GrantType.AuthorizationCode,
GrantType.ClientCredentials
},
AllowedScopes =
{
"WebApi.All",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles"
},
RedirectUris = { "https://localhost:44305/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:44305/Home/Index" },
AlwaysIncludeUserClaimsInIdToken = false,
AllowOfflineAccess = true,
}
};
For testing purposes I add users manually from Program.cs
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>();
AddUsers(userManager).GetAwaiter().GetResult();
}
host.Run();
}
private static async Task AddUsers(UserManager<IdentityUser> userManager)
{
var adminClaim = new Claim("role", "Admin");
var visitorClaim = new Claim("role", "Visitor");
var user = new IdentityUser("Admin");
await userManager.CreateAsync(user, user.UserName);
await userManager.AddClaimAsync(user, adminClaim);
user = new IdentityUser("Visitor");
await userManager.CreateAsync(user, user.UserName);
await userManager.AddClaimAsync(user, visitorClaim);
}
So if I use manual access token retrieval and add it myself to the HttpClient headers, then my endpoint is reached and returns expected response. If I use .AddClientAccessTokenHandler(), I get 403 - Forbidden. What am I missing?
Since you are registering the client under the name auth, you also should retrieve it as such.
This basically means I expect you to use something like this, or it's equivalent:
_httpClient = factory.CreateClient("auth");
Basically this mechanism ensures you're able to retrieve HttpClients for various API's and settings.
ps. I am on mobile; and currently not very good access to my resources.

JWT Token Remove or logout

I'm doing user-controlled using JWT token.
No problem logging in, but how to log out?
Comparison of the database
my opinion,
do you have better method suggestions
Token controller
I validate the user in UyelikOnaylama class
public class TokenController : ApiController
{
[HttpPost]
public async Task<HttpResponseMessage> Post(TokenRequestDto dto)
{
UyelikOnaylama uyelikOnaylama = new UyelikOnaylama();
var sonuc = await uyelikOnaylama.AsekronMethod(dto);
Random random = new Random();
if (sonuc==1)
{
var claims = new[]
{
new Claim(ClaimTypes.Name, dto.UserName),
new Claim(ClaimTypes.Role, random.ToString()+"asd"),
new Claim("scope", random.ToString()+"tasd"),
new Claim("scope", "**")
};
var token = new JwtSecurityToken(
issuer: "localhost",
audience: "localhost",
claims: claims,
expires: DateTime.UtcNow.AddMonths(30),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("!^'+sda1905SDASDQdqqdD'^+!34123")), SecurityAlgorithms.HmacSha256)
);
return Request.CreateResponse(HttpStatusCode.OK, new JwtSecurityTokenHandler().WriteToken(token));
}
else
{
return Request.CreateResponse(HttpStatusCode.Unauthorized, "Hatalı kullanıcı adı ya da parola");
}
}
}
I'm checking with a startup class
public class Startup
{
public void Configuration(IAppBuilder app)
{
string secretKey = "!^'+sda1905SDASDQdqqdD'^+!34123";
var opt = new JwtBearerAuthenticationOptions();
var prov = new SymmetricKeyIssuerSecurityKeyProvider[1];
prov[0] = new SymmetricKeyIssuerSecurityKeyProvider("localhost", Encoding.UTF8.GetBytes(secretKey));
opt.IssuerSecurityKeyProviders = prov;
opt.AllowedAudiences = new String[1] { "localhost" };
app.UseJwtBearerAuthentication(opt);
}
}
Correct me if I am wrong, but you get an AccessToken from your JWT Service? With this Token you get the desired rights for accessing data on the WebApi (or whatever you do with it). If your User logs out, the AccessToken is still available.
If this is your problem, simply remove the token from the List holding all of them. Also you can reduce the time, when the Token expires
Solution
Add this 3 classes into your project
public static class JwtSecurityKey
{
public static SymmetricSecurityKey Create(string secret)
{
return new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secret));
}
}
public sealed class JwtToken
{
private JwtSecurityToken Token;
internal JwtToken(JwtSecurityToken token)
{
this.Token = token;
}
public DateTime ValidTo => Token.ValidTo;
public string Value => new JwtSecurityTokenHandler().WriteToken(this.Token);
}
public class JwtTokenBuilder
{
private SecurityKey SecurityKey = null;
private string Subject = "";
private string Issuer = "";
private string Audience = "";
private Dictionary<string, string> Claims = new Dictionary<string, string>();
private int ExpiryInMinutes = 5;
public JwtTokenBuilder AddSecurityKey(SecurityKey securityKey)
{
this.SecurityKey = securityKey;
return this;
}
public JwtTokenBuilder AddSubject(string subject)
{
this.Subject = subject;
return this;
}
public JwtTokenBuilder AddIssuer(string issuer)
{
this.Issuer = issuer;
return this;
}
public JwtTokenBuilder AddAudience(string audience)
{
this.Audience = audience;
return this;
}
public JwtTokenBuilder AddClaim(string type, string value)
{
this.Claims.Add(type, value);
return this;
}
public JwtTokenBuilder AddClaims(Dictionary<string, string> claims)
{
this.Claims.Union(claims);
return this;
}
public JwtTokenBuilder AddExpiry(int expiryInMinutes)
{
this.ExpiryInMinutes = expiryInMinutes;
return this;
}
public JwtToken Build()
{
EnsureArguments();
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, this.Subject),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
}
.Union(this.Claims.Select(item => new Claim(item.Key, item.Value)));
var token = new JwtSecurityToken(
issuer: this.Issuer,
audience: this.Audience,
claims: claims,
expires: DateTime.UtcNow.AddMinutes(ExpiryInMinutes),
signingCredentials: new SigningCredentials(
this.SecurityKey,
SecurityAlgorithms.HmacSha256));
return new JwtToken(token);
}
#region Privates
private void EnsureArguments()
{
if (this.SecurityKey == null)
throw new ArgumentNullException("Security Key");
if (string.IsNullOrEmpty(this.Subject))
throw new ArgumentNullException("Subject");
if (string.IsNullOrEmpty(this.Issuer))
throw new ArgumentNullException("Issuer");
if (string.IsNullOrEmpty(this.Audience))
throw new ArgumentNullException("Audience");
}
#endregion
}
And in your Startup class, call this method:
private void ConfigureTokenServices(IServiceCollection services)
{
// Add Token Authentication
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "Custom.Security.Bearer",
ValidAudience = "Custom.Security.Bearer",
IssuerSigningKey = JwtSecurityKey.Create("Yout securitykey which must be a very long string to work")
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
Debug.WriteLine("OnAuthenticationFailed: " + context.Exception.Message);
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
Debug.WriteLine("OnTokenValidated: " + context.SecurityToken);
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Guest",
policy => policy.RequireClaim("Role", "Add here your roles"));
});
}
And add this line
app.UseAuthentication();
to
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
With this you can then filter inside your Controller, which is the sense of JWT:
[Produces("application/json")]
[Route("YourRoute")]
[Authorize("Role")]
public class MyController
{
or you can do this directly on a method.
[Authorize("Role")]
[HttpGet, Route("YourRoute")]
public IActionResult HttpGet()
{
Tell me if I understood your issue correct and if there are any problems implementing this

IdentityServer4 with net4.5 client

I have to connect my existing MVC project written in .net 4.5 to IdentityServer4. Yesterday I tried this solution: https://stackoverflow.com/a/39771372, and it's working, but I need to handle callback and load additional user data from client app database. I've tried to change RedirectUri to my own Controller method, but it is not called.
Today I trying to use Implicit Flow from sample: https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Clients/src/MvcManual - i know that sample is net.core, but now I can handle callback from IdentityServer. Now how can I validate token? I have problem with whole ValidateIdentityToken method
I decoded token using:
var token = new JwtSecurityToken(jwtEncodedString: idToken);
In token I found my user info, but I think it is not safe method.
Finally I have two questions:
Can I simply configure my client to redirect to my controller method where I loading additional user data like "sitemap" from Database? It is possible using first sample?
Using second sample, anyone knows how to validate token in net4.5 client?
After validation I need only Subject and username to load additional data.
EDIT: My configuration
IdentityServer4 client configuration:
a) Hybrid
new Client
{
ClientName = "mvc Client",
ClientId = "mvc",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RedirectUris = { "http://localhost:5002/Account/Callback" }, // where to redirect to after login
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }, // where to redirect to after logout
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api"
},
ClientSecrets =
{
new Secret("secret".Sha256())
},
RequireConsent = false,
AlwaysIncludeUserClaimsInIdToken = true
}
b) Implicit method
new Client
{
ClientName = "mvc Client",
ClientId = "mvc",
AllowedGrantTypes = {GrantType.ClientCredentials, GrantType.Implicit},
RedirectUris = { "http://localhost:5002/Account/Callback" }, // where to redirect to after login
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }, // where to redirect to after logout
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api"
},
ClientSecrets =
{
new Secret("secret".Sha256())
},
RequireConsent = false,
AlwaysIncludeUserClaimsInIdToken = true
}
MVC .net4.5 configuration
a) using Microsoft.Owin.Security.OpenIdConnect, where RedirectUri is not called
Startup.cs
public void ConfigureAuthentication(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "http://localhost:5000", //ID Server
ClientId = "mvc",
ResponseType = "id_token code",
SignInAsAuthenticationType = "Cookies",
RedirectUri = "http://localhost:5002/Account/Callback", //URL of website
Scope = "openid profile",
});
}
b) Using second method Implicit
Startup.cs
public void ConfigureAuthentication(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
LoginPath = new PathString("/Account/Secure")
});
}
AccountController
public class AccountController : BaseController
{
[AllowAnonymous]
public async Task<ActionResult> Secure()
{
return await StartAuthentication();
}
public async Task<ActionResult> Logout()
{
Authentication.SignOut("Cookies");
var disco = await DiscoveryClient.GetAsync(Constants.Authority);
return Redirect(disco.EndSessionEndpoint);
}
[AllowAnonymous]
private async Task<ActionResult> StartAuthentication()
{
// read discovery document to find authorize endpoint
var disco = await DiscoveryClient.GetAsync(Constants.Authority);
var authorizeUrl = new AuthorizeRequest(disco.AuthorizeEndpoint).CreateAuthorizeUrl(
clientId: "mvc",
responseType: "id_token",
scope: "openid profile",
redirectUri: "http://localhost:5002/Account/Callback",
state: "random_state",
nonce: "random_nonce",
responseMode: "form_post");
return Redirect(authorizeUrl);
}
public async Task<ActionResult> Callback()
{
var state = Request.Form["state"].ToString();
var idToken = Request.Form["id_token"].ToString();
if (!string.Equals(state, "random_state")) throw new Exception("invalid state");
var user = await ValidateIdentityToken(idToken, state);
var id = new ClaimsIdentity(user, "Cookies");
Authentication.SignIn(new AuthenticationProperties
{
IsPersistent = false
}, id);
//Here Loading other data for user from Database e.g SiteMap
// {...}
return Redirect("/");
}
private async Task<ClaimsPrincipal> ValidateIdentityToken(string idToken)
{
// working area
var token = new JwtSecurityToken(jwtEncodedString: idToken);
Console.WriteLine("email => " + token.Claims.First(c => c.Type == "email").Value);
//working area
//need to return user Claims from validated token. How to?
}
BaseController
[Authorize]
public abstract class BaseController : Controller
{
public IAuthenticationManager Authentication
{
get { return this.HttpContext.GetOwinContext().Authentication; }
}
// Methods that can be used in my other controllers.
}

c# WebAPI Owin jwt RefreshToken invalid_grant

I am stumped by this behavior. Basically, when a refresh of a token is requested, WebAPI goes through the logic of removing the old refresh_token from the data, and I don't see any errors in the debugger. However, the API returns a HTTP 400 with "invalid_grant" as the error.
Startup.cs
// OAuth Server configuration
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/oauth2/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(1),
AccessTokenFormat = new AccessTokenJwtFormat(issuer),
RefreshTokenProvider = new SimpleRefreshTokenProvider(),
RefreshTokenFormat = new RefreshTokenJwtFormat(issuer),
Provider = new CustomOAuthProvider()
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
SimpleRefreshTokenProvider.cs
public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var clientid = context.Ticket.Properties.Dictionary["as:client_id"];
if (string.IsNullOrEmpty(clientid))
{
return;
}
var refreshTokenId = Guid.NewGuid().ToString("n");
var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime");
var _repo = ClientDbProvider.GetInstance();
var token = new RefreshToken()
{
Id = ClientHelper.GetHash(refreshTokenId),
ClientId = clientid,
Subject = context.Ticket.Identity.Name,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
};
context.Ticket.Properties.IssuedUtc = new DateTimeOffset(token.IssuedUtc);
context.Ticket.Properties.ExpiresUtc = new DateTimeOffset(token.ExpiresUtc);
context.Ticket.Properties.Dictionary.Add("refreshTokenId", refreshTokenId);
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.Role, "refreshToken"));
token.ProtectedTicket = context.SerializeTicket();
var result = await _repo.AddRefreshToken(token);
if (result)
{
context.SetToken(token.ProtectedTicket);
}
return;
}
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
var _repo = ClientDbProvider.GetInstance();
string hashedTokenId = ClientHelper.GetHash(context.Token);
var refreshToken = await _repo.FindRefreshToken(hashedTokenId);
if (refreshToken != null)
{
//Get protectedTicket from refreshToken class
context.DeserializeTicket(refreshToken.ProtectedTicket);
var result = await _repo.RemoveRefreshToken(hashedTokenId);
}
}
public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}
public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
}
RefreshTokenJwtFormat.cs
public class RefreshTokenJwtFormat : ISecureDataFormat<AuthenticationTicket>
{
private const string AudiencePropertyKey = "audience";
private readonly string _issuer = string.Empty;
public RefreshTokenJwtFormat(string issuer)
{
_issuer = issuer;
audStore = new AudiencesStore();
}
public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
string audienceId = data.Properties.Dictionary.ContainsKey(AudiencePropertyKey) ? data.Properties.Dictionary[AudiencePropertyKey] : null;
if (string.IsNullOrWhiteSpace(audienceId)) throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");
var audience = GetAudience(audienceId);
string symmetricKeyAsBase64 = audience.Base64Secret;
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingCredentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(keyByteArray),
SecurityAlgorithms.HmacSha256Signature,
SecurityAlgorithms.Sha256Digest);
var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc;
var payload = new JwtPayload(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime);
if (data.Properties.Dictionary.ContainsKey("refreshTokenId"))
{
payload.Add("refreshTokenId", data.Properties.Dictionary["refreshTokenId"]);
}
var header = new JwtHeader(signingCredentials);
var token = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.WriteToken(token);
return jwt;
}
public AuthenticationTicket Unprotect(string protectedText)
{
var handler = new JwtSecurityTokenHandler();
SecurityToken securityToken = handler.ReadToken(protectedText);
var audienceId = ((JwtSecurityToken)securityToken).Claims.First(x => x.Type == "aud").Value;
var audience = GetAudience(audienceId);
string symmetricKeyAsBase64 = audience.Base64Secret;
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var securityKey = new InMemorySymmetricSecurityKey(keyByteArray);
var validationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = securityKey,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
ValidateAudience = true,
ValidAudience = audienceId,
ValidateIssuer = true,
ValidIssuer = _issuer
};
SecurityToken validatedToken;
ClaimsPrincipal principal = null;
try
{
principal = handler.ValidateToken(protectedText, validationParameters, out validatedToken);
}
catch(Exception ex)
{
return null;
}
return new AuthenticationTicket(principal.Identities.First(), new AuthenticationProperties());
}
private Models.Audience GetAudience(string audienceId)
{
var findAudTask = Task.Run(() => audStore.FindAudienceAsync(audienceId));
findAudTask.Wait();
var audience = findAudTask.Result;
return audience;
}
private AudiencesStore audStore;
}
First you need
implement GrantRefreshToken(OAuthGrantRefreshTokenContext context) in your CustomOAuthProvider
something like
public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
// Change auth ticket for refresh token requests
var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
//newIdentity.AddClaim(new Claim("newClaim", "newValue"));
var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
context.Validated(newTicket);
return Task.FromResult<object>(null);
}
Second you need to change your method Unprotect in RefreshTokenJwtFormat.
replace
return new AuthenticationTicket(principal.Identities.First(), new AuthenticationProperties());
with
return new AuthenticationTicket(principal.Identities.First(), new AuthenticationProperties
{
IssuedUtc = validatedToken.ValidFrom,
ExpiresUtc = validatedToken.ValidTo
});
i have similar (working) code. I'm not a specialist on this but i compared my code a bit and noticed:
in SimpleRefreshToken.cs:
in receiveAsync, my code ends with:
context.SetTicket(context.Ticket);
return Task.FromResult<object>(null);
Which sets the ticket and return a value.
The same for createAsync, my code ends with:
return Task.FromResult<object>(null);
Allthough, no idea if this will help

MVC with Owin JWT Identity

I am trying to figure out how to get the claim out of my token.
I will try an keep the explanation short
I have an HTML page that does a post to my web api, does and auth
check and returns an JWT token
when i get the token back i want to send it to different url, and the way i am doing it is using a querystring. I know i can use cookies but for this app we dont want to use them. So if my url looks like this http://somedomain/checkout/?token=bearer token comes here
I am using Owin middleware and this is what i have so far
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
Provider = new ApplicationOAuthBearerAuthenticationProvider(),
});
public class ApplicationOAuthBearerAuthenticationProvider
: OAuthBearerAuthenticationProvider
{
public override Task RequestToken(OAuthRequestTokenContext context)
{
if (context == null)
throw new ArgumentNullException("context");
var token = HttpContext.Current.Request.QueryString["token"];
if (!string.IsNullOrEmpty(token))
context.Token = token;
return Task.FromResult<object>(null);
}
}
But how do i get the Claims out of the Token or just check the IsAuthenticated
I tried the Following inside my controller just to check, but the IsAuthenticated is always false
var identity = (ClaimsIdentity) HttpContext.Current.GetOwinContext().Authentication.User.Identity;
if (!identity.IsAuthenticated)
return;
var id = identity.FindFirst(ClaimTypes.NameIdentifier);
OK so I managed to figure it out. The above code that I had is all working well but I needed to add the UseJwtBearerAuthentication middle ware.
One thing I did end up changing from my original code was i changed the context.Token = token; to context.Request.Headers.Add("Authorization", new[] { string.Format("Bearer {0}", token) });
So my startup class looks like this...
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
Provider = new ApplicationOAuthBearerAuthenticationProvider(),
});
app.UseJwtBearerAuthentication(JwtOptions());
ConfigureAuth(app);
}
private static JwtBearerAuthenticationOptions JwtOptions()
{
var key = Encoding.UTF8.GetBytes(ConfigurationManager.AppSettings["auth:key"]);
var jwt = new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = Some Audience,
ValidIssuer = Some Issuer,
IssuerSigningToken = new BinarySecretSecurityToken(key),
RequireExpirationTime = false,
ValidateLifetime = false
}
};
return jwt;
}
public class ApplicationOAuthBearerAuthenticationProvider
: OAuthBearerAuthenticationProvider
{
public override Task RequestToken(OAuthRequestTokenContext context)
{
if (context == null)
throw new ArgumentNullException("context");
var token = HttpContext.Current.Request.QueryString["token"];
if (!string.IsNullOrEmpty(token))
context.Request.Headers.Add("Authorization", new[] { string.Format("Bearer {0}", token) });
return Task.FromResult<object>(null);
}
}
}

Categories