I have a web application. My requirement is that i need to generate oauth2 bearer token on every login. Currently we are using thinktecture to generate token, but this procedure is taking almost 7 seconds to generate token everytime. Is there any way i can generate token without using thinktecture ?
If you have created a new ASP.NET Web Application -> Web API with Individual User Accounts. Have a look at App_Start -> Startup.Auth.cs.
It should contain something like this:
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
This means that you can send a request for an access token, example request:
You can then verify that the access token works:
With this token you can now access all protected resources that the user has access to.
Asp.net default implementation will use DPAPI in your Authorization Server, so it will use the “validationKey” value in machineKey node stored in machine.config file to issue the access token and protect it. The same case applies when you send the access token to your Resource Server, it will use the same machineKey to decrypt the access token and extract the authentication ticket from it.
ASP.NET
If you want to generate a JWT encoded Bearer Token, you should override ISecureDataFormat<AuthenticationTicket>.Protect() Method:
CustomJwtFormat.cs
string symmetricKeyAsBase64 = audience.Base64Secret;
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingKey = new HmacSigningCredentials(keyByteArray);
var issued = data.Properties.IssuedUtc; var expires = data.Properties.ExpiresUtc;
JwtSecurityToken token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime,expires.Value.UtcDateTime, signingKey);
var handler = new JwtSecurityTokenHandler();
//serialize the JSON Web Token to a string
var jwt = handler.WriteToken(token);
return jwt;
Add your custom JWT formatter to OAuth Option
OAuthAuthorizationServerOptions OAuthServerOptions = new
OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
AccessTokenFormat = new CustomJwtFormat("http://localhost:5001")
};
// Generation and validation
app.UseOAuthBearerTokens(OAuthServerOptions);
The app.UseOAuthBearerTokens helper method creates both the token server and the middleware to validate tokens for requests in the same application.
If this is an Authorization server(generate token) , you should use app.UseOAuthAuthorizationServer(OAuthServerOptions) in the last line
ASP.NET Core
Unforturnately, the ASP.NET team simply decided not to port OAuthAuthorizationServerMiddleware to asp.net core: https://github.com/aspnet/Security/issues/83
community-provided, open source authentication options for ASP.NET Core:
AspNet.Security.OpenIdConnect.Server:low-level, protocol-first OpenID Connect server framework for ASP.NET Core and OWIN/Katana.
IdentityServer:OpenID Connect and OAuth 2.0 framework for ASP.NET Core, officially certified by the OpenID Foundation and under governance of the .NET Foundation.
OpenIddict: easy-to-use OpenID Connect server for ASP.NET Core.
I followed below article http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
Downloaded their sourcecode and checked it. They have good example on how to create token.
Related
I have created Asp.net WebApi and enable TwitterAuthentication code.
On HomeController.cs used [Authorize] attribute.
Now how can I verify credentials and give access to Authorize Controller without open login box ?
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
app.UseTwitterAuthentication(
consumerKey: "mykey",
consumerSecret: "mysecret");
}
I have added one application into twitter app - get the consumer key.
and consumer secret.
I do not want a twitter login popup to be opened
for login credentials while authorizing webapi.
We have a web app built on Asp.Net core. It doesn't contain any authentication middleware configured in it.
We are hosting on Azure App Service and using the Authentication/Authorization option (EasyAuth) to authenticate against Azure AD.
The authentication works well - we get the requisite headers inserted and we can see the authenticated identity at /.auth/me. But the HttpContext.User property doesn't get populated.
Is this a compatibility issue for Asp.Net core? Or am I doing something wrong?
I've created a custom middleware that populates the User property until this gets solved by the Azure Team.
It reads the headers from the App Service Authentication and create a a user that will be recognized by the [Authorize] and has a claim on name.
// Azure app service will send the x-ms-client-principal-id when authenticated
app.Use(async (context, next) =>
{
// Create a user on current thread from provided header
if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
{
// Read headers from Azure
var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
// Create claims id
var claims = new Claim[] {
new System.Security.Claims.Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", azureAppServicePrincipalIdHeader),
new System.Security.Claims.Claim("name", azureAppServicePrincipalNameHeader)
};
// Set user in current context as claims principal
var identity = new GenericIdentity(azureAppServicePrincipalIdHeader);
identity.AddClaims(claims);
// Set current thread user to identity
context.User = new GenericPrincipal(identity, null);
};
await next.Invoke();
});
Yes, this is a compatibility issue. ASP.NET Core does not support flowing identity info from an IIS module (like Easy Auth) to the app code, unfortunately. This means HttpContext.User and similar code won't work like it does with regular ASP.NET.
The workaround for now is to invoke your web app's /.auth/me endpoint from your server code to get the user claims. You can then cache this data as appropriate using the x-ms-client-principal-id request header value as the cache key. The /.auth/me call will need to be properly authenticated in the same way that calls to your web app need to be authenticated (auth cookie or request header token).
I wrote a small basic middleware to do this. It will create an identity based off of the .auth/me endpoint. The identity is created in the authentication pipeline so that [authorize] attributes and policies work with the identity.
You can find it here:
https://github.com/lpunderscore/azureappservice-authentication-middleware
or on nuget:
https://www.nuget.org/packages/AzureAppserviceAuthenticationMiddleware/
Once added, just add this line to your startup:
app.UseAzureAppServiceAuthentication();
The following code decrypts the AAD token from the Azure App Service HTTP header and populates HttpContext.User with the claims. It's rough as you'd want to cache the configuration rather than look it up on every request:
OpenIdConnectConfigurationRetriever r = new OpenIdConnectConfigurationRetriever();
ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.Endpoint, r);
OpenIdConnectConfiguration config = await configManager.GetConfigurationAsync();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKeys = config.SigningKeys.ToList(),
ValidateIssuer = true,
ValidIssuer = config.Issuer,
ValidateAudience = true,
ValidAudience = options.Audience,
ValidateLifetime = true,
ClockSkew = new TimeSpan(0, 0, 10)
};
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = null;
SecurityToken validToken = null;
string token = context.Request.Headers["X-MS-TOKEN-AAD-ID-TOKEN"];
if (!String.IsNullOrWhiteSpace(token))
{
principal = handler.ValidateToken(token, tokenValidationParameters, out validToken);
var validJwt = validToken as JwtSecurityToken;
if (validJwt == null) { throw new ArgumentException("Invalid JWT"); }
if (principal != null)
{
context.User.AddIdentities(principal.Identities);
}
}
It only works for Azure AD. To support other ID providers (Facebook, Twitter, etc) you'd have to detect the relevant headers and figure out how to parse each provider's token. However, it should just be variations on the above theme.
You can give this library a try. I faced a similar problem and created this to simplify the use.
https://github.com/dasiths/NEasyAuthMiddleware
Azure App Service Authentication (EasyAuth) middleware for ASP.NET
CORE with fully customizable components with support for local
debugging
It hydrates the HttpContext.User by registering a custom authentication handler. To make things easier when running locally, it even has the ability to use a json file to load mocked claims.
I am using the following code to successfully get a token from my MVC web app. However I am unsure how to retrieve the claims that I have added. Should they be returned in the same response as my token?
Thanks!
Startup.cs:
app.UseJwtBearerAuthentication(options =>
{
options.AutomaticAuthenticate = true;
options.Audience = "resource_server";
options.Authority = "https://www.example.com/";
options.RequireHttpsMetadata = false;
});
app.UseOpenIdConnectServer(options =>
{
options.ApplicationCanDisplayErrors = true;
options.AllowInsecureHttp = false;
options.Provider = new AuthorizationProvider();
options.TokenEndpointPath = "/connect/token";
});
Adding claims:
identity.AddClaim("custom_claim", "value", "token id_token");
foreach (string role in await userManager.GetRolesAsync(user))
{
identity.AddClaim(ClaimTypes.Role, role, "id_token token");
}
This is my PostAsync result:
{"resource":"resource_server","scope":"openid profile","token_type":"bearer","access_token":"eyJhbGciOiJSU....","expires_in":"3600"}
Should they be returned in the same response as my token?
Since you're specifying both the id_token and token destinations, your claims should be copied in both the access token and the identity token. You should be able to use any JSON parser to extract the claims you're looking for from the access_token/id_token properties.
Two remarks:
In ASOS beta4, you had to explicitly add scope=openid to your token request to get back an identity token, even if you called ticket.SetScopes("openid"), which probably explains why there's no id_token property in the response you shared. This policy was relaxed in the next version.
In ASOS beta4 (for ASP.NET Core RC1), access tokens were serialized using the JWT format. This is no longer true with the beta5 version, that uses an encrypted format by default. Don't try to read them from the client application: instead, use the id_token, which is meant to be consumed by the client app.
I am currently struggling with setting the timeout on the cookie/auth token when authenticating my .NET Core App using Azure AD via the OpenIdConnect authentication model.
The sign-in scheme is being set in the ConfigureServices method via the following:
services.AddAuthentication(options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
I am then setting up my configuration as follows:
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
CookieName = "MyCookie",
ExpireTimeSpan = TimeSpan.FromHours(2)
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions()
{
Authority = authorityUri.AbsoluteUri,
ClientId = azureOptions.ClientId,
ClientSecret = azureOptions.ClientSecret,
ResponseType = OpenIdConnectResponseTypes.CodeIdToken,
Events = new OpenIdConnectEvents()
{
OnAuthorizationCodeReceived = async context =>
{
await aAuthenticateMiddleware.OnAuthenticate(context, logger);
}
}
});
app.UseMiddleware<aAuthenticateMiddleware>();
Note, that I am not using the built in Identity (as its not practical for our purposes) but rather using a custom middleware.
Within the middleware layer I am checking whether the user is authenticated and if not a challenge is issued:
var authenticationProperties = new AuthenticationProperties() { RedirectUri = context.Request.Path.Value ?? "/" };
authenticationProperties.AllowRefresh = false;
authenticationProperties.IssuedUtc = DateTime.Now;
authenticationProperties.ExpiresUtc = DateTime.Now.AddHours(2);
await context.Authentication.ChallengeAsync(
authenticationManager.IdentityProvider.AuthenticationScheme,
authenticationProperties,
ChallengeBehavior.Automatic
);
This is all works fine and authenticates the user correctly etc however this is issuing the auth token (and cookie) with a 15 minute expiry and ignoring my 2 hour expiry that I have tried setting.
I have been referring to the latest source examples from GitHub from the aspnet/security repository for examples.... however none of these mention anything about overriding the default expiry issued.
https://github.com/aspnet/Security/tree/dev/samples/OpenIdConnect.AzureAdSample
Most examples I have found are still referencing the old AspNet libraries rather than the AspNetCore libraries.
Some articles suggest that using the SignInAsync with persistent set to True allows the ExpireTimeSpan to be honored, however this throws a "Not Supported Exception" when calling it. Perhaps SignInAsync is not supported via Azure AD?
Does anyone have any insight on how to achieve this?
in UseOpenIdConnectAuthentication set UseTokenLifetime = false
I have implemented custom asp.net identity with database first approach. I have implemented token based implementation using OWIN.
app.CreatePerOwinContext<OVT_UserEntities>(() => new OVT_UserEntities());
app.CreatePerOwinContext<UserManager<User, int>>(
(IdentityFactoryOptions<UserManager<User, int>> options, IOwinContext context) =>
new UserManager<User, int>(new UserStore(context.Get<OVT_UserEntities>())));
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/token"),
Provider = new OVTApplicationOAuthProvider(
"self", () => HttpContext.Current.GetOwinContext().GetUserManager<UserManager<User, int>>()),
AuthorizeEndpointPath = new PathString("/api/account/authorize"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
});
OVT_UserEntities is my custom db context which will validate the entered username with my own database.
now i want to do active directory authentication for organizational users account.
How can i implement both database asp.net identity authentication + active directory implementation in asp.net identity authentcation.
if the user enters his creditentials, first i will check in database ,if it's not available then will go for active directory for further checking. if is avail in AD(active directory) then will redirect some other page by getting some tokens.
any references would be appreciated.