I'm trying to build a custom AuthenticationHandler in ASP.Net Core 2. Following up topic like ASP.NET Core 2.0 authentication middleware and Why is Asp.Net Core Authentication Scheme mandatory, I've created the specific classes. The registering happens like this:
services.AddAuthentication(
options =>
{
options.DefaultScheme = Constants.NoOpSchema;
options.DefaultAuthenticateScheme = Constants.NoOpSchema;
options.DefaultChallengeScheme = Constants.NoOpSchema;
options.DefaultSignInScheme = Constants.NoOpSchema;
options.DefaultSignOutScheme = Constants.NoOpSchema;
options.DefaultForbidScheme = Constants.NoOpSchema;
}
).AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
Everything works, if the specific controllers set the Scheme explicitely:
[Authorize(AuthenticationSchemes= Constants.NoOpSchema)]
[Route("api/[controller]")]
public class IndividualsController : Controller
But I would like to not have to set the Schema, since it should get added dynamically. As soon as I remove the Scheme Property, like this:
[Authorize]
[Route("api/[controller]")]
public class IndividualsController : Controller
It doesn't work anymore.
I would have hoped, that setting the DefaultScheme Properties does this job. Interesting enough, I didn't find any specific discussion about this topic.
Am I doing something wrong here or is my expected outcome wrong?
Edit: Thanks for the questions, it helped me a lot. It seems like mapping the DefaultScheme is using by the Authentication Middleware, which I only used, when the CustomAuthHandler was not in place. Therefore I had to add the AuthenticationMiddleware always.
Edit2: Unfortunately, it still doesn't work. To enhance a bit my question: I'm adding the middleware as usual:
app.UseAuthentication();
app.UseMvc();
Now I get into my Handler, which is looking like this:
public class NoOpAuthHandler : AuthenticationHandler<NoOpAuthOptions>
{
public const string NoOpSchema = "NoOp";
public NoOpAuthHandler(IOptionsMonitor<NoOpAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync() => Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, NoOpSchema)));
}
But even if I always return success, I get an 401. I think I have to dig deeper and kindahow set some Claims, but unfortunately, the Handlers from Microsoft are quite hard to analyze, since they contain a lot of Code.
ASP.NET Core 2 Answer
You have to set a default authorization policy tied to your authentication scheme:
services.AddAuthorization(options => {
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(Constants.NoOpSchema)
.RequireAuthenticatedUser()
.Build();
});
ASP.NET Core 3 Answer
In ASP.NET Core 3 things apparently changed a bit, so you would want to create an extension method to add your authentication handler:
public static class NoOpAuthExtensions
{
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder)
=> builder.AddNoOpAuth(NoOpAuthHandler.NoOpSchema, _ => { });
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, Action<NoOpAuthOptions> configureOptions)
=> builder.AddNoOpAuth(NoOpAuthHandler.NoOpSchema, configureOptions);
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, string authenticationScheme, Action<NoOpAuthOptions> configureOptions)
=> builder.AddNoOpAuth(authenticationScheme, null, configureOptions);
public static AuthenticationBuilder AddNoOpAuth(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<NoOpAuthOptions> configureOptions)
{
return builder.AddScheme<NoOpAuthOptions, NoOpAuthHandler>(authenticationScheme, displayName, configureOptions);
}
}
And use it in your ConfigureServices method like this:
services
.AddAuthentication(NoOpAuthHandler.NoOpSchema)
.AddNoOpAuth();
Make sure that you have Authentication middleware in your pipeline and place it before MVC.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
///
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
///
}
UPDATE
try using this code in HandleAuthenticateAsync method.
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
List<Claim> claims = new List<Claim>();
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, Scheme.Name);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
AuthenticationTicket authenticationTicket = new AuthenticationTicket(claimsPrincipal, Scheme.Name);
return AuthenticateResult.Success(authenticationTicket);
}
I suffer this for hours, in my case problem was default AuthenticationMiddleware class.
More specifically;
If you set ClaimsPrincipal within custom middleware in your request pipeline like below;
HttpContext.context.User = new ClaimsPrincipal(identity);
this will override your default auth config settings,
What I did to solve; remove custom middleware and add app.UseAuthentication(); in Configure section in Startup.cs, and Authorize attribute checks whatever set in config section as default;
Here is mine;
services.AddAuthentication(x =>
{
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateLifetime = true,
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
});
in .NET Core 3.1, I had to manually add [Authorize(AuthenticationSchemes = "Bearer")] instead of a plain [Authorize] to endpoints in order for authentication to function as I'd expect. The following configuration change solved the issue:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Bearer";
})
try this.
services.AddAuthentication(
options =>
{
options.DefaultAuthenticateScheme = "Cookie"
options.DefaultChallengeScheme = Constants.NoOpSchema;
options.DefaultSignInScheme = "Cookie";
}
)
.AddCookie("Cookie")
.AddScheme<CustomAuthOptions, CustomAuthHandler>(Constants.NoOpSchema, "Custom Auth", o => { });
Related
I'm trying to add auth to my .NET Core 3.1 application, however each attempt to use the returned JWT results in 401 Unauthorized. I've gone through a few steps to debug:
I've confirmed that the JWT that my authenticate endpoint returns is valid, using this online validator.
I've re-ordered my UseRouting(), UseAuthentication(), UseAuthorization(), and UseEndpoints() to every possible order.
I've disabled both audience and issuer validation entirely for the time being.
Can someone identify where I've gone wrong, or at the very least, provide some method of properly debugging so I can track the issue down? Thanks. Code below.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
var key = Encoding.UTF8.GetBytes("thisismycustomSecretkeyforauthentication");
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "issuer",
ValidAudience = "audience",
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});
services
.AddControllers();
.AddMvc(options => { options.EnableEndpointRouting = false; });
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app
.UseStaticFiles()
.UseHsts()
.UseHttpsRedirection()
.UseMvc(routes => routes.MapRoute(name: "default", template: "{controller=App}/{action=Index}/{id?}"))
.UseRouting()
.UseAuthentication()
.UseAuthorization()
.UseEndpoints(endpoints => { endpoints.MapControllers(); });
if (env.IsDevelopment())
app.UseSpa(spa => spa.UseProxyToSpaDevelopmentServer("https://localhost:22010"));
}
AuthController.cs
[ApiController]
[Authorize]
[Route("[controller]")]
public class AuthController : Controller
{
[AllowAnonymous]
[HttpPost("authenticate")]
public async Task<IActionResult> Authenticate(AuthenticationRequest request)
{
if (request.Username != "test" || request.Password != "admin")
return Unauthorized();
var tokenHandler = new JwtSecurityTokenHandler();
var tokenKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("thisismycustomSecretkeyforauthentication"));
var token = new JwtSecurityToken
(
issuer: null,
audience: null,
claims: new Claim[] { new Claim(ClaimTypes.Name, request.Username) },
expires: DateTime.Now.AddDays(30),
signingCredentials: new SigningCredentials(tokenKey, SecurityAlgorithms.HmacSha256)
);
var tokenResponse = tokenHandler.WriteToken(token);
return Ok(tokenResponse);
}
[HttpGet]
public IActionResult Do()
{
return Ok("Done!");
}
}
Authentication setup looks fine, and your middleware order is per Microsoft Documentation.
Based on the code provided you seem to be missing the actual Authorization options. This is similar to the issue solved in this question.
I am having some difficulty getting multiple authenticaion schemes to work with my .NET Core API.
Each works perfectly when set as the Default Scheme to be used, but I cannot get them to chain authenticaion, so if one fails authentication it moves onto the next one in the chain to try and authenticate using that scheme.
I'm using
JWT Bearer Token Authentication
API Key Authentication
As can be seen in the code below I've setup an AuthorizeFilter policy with the multiple schemes, but obviously I'm missing something somewhere along the way and I'm hoping you may be able to spot what I am missing.
Below is the complete start up code I am using.
Kind Regards
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(authOptions =>
{
authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(bearerOptions =>
{
bearerOptions.RequireHttpsMetadata = true;
bearerOptions.SaveToken = true;
bearerOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = JWTProvider.CLAIM_ISSUER,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(this.Configuration[JWTSecurityKeyProvider.DEFAULT_JWT_SECURITY_KEYNAME])) { KeyId = "416" },
ValidAudience = JWTProvider.API_AUDIENCE,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(1)
};
})
.AddApiKeySupport(options =>
{
});
services.AddControllers(options =>
{
var defaultSchemes = new[] { JwtBearerDefaults.AuthenticationScheme, ApiKeyAuthenticationOptions.DefaultScheme };
var defaultPolicy = new AuthorizationPolicyBuilder(defaultSchemes)
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(defaultPolicy));
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Auth API", Version = "v1" });
});
services.AddSingleton<JWTSecurityKeyProvider>();
services.AddSingleton<JWTProvider>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Auth API v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
According to documentation:
Only one JWT bearer authentication is registered with the default authentication scheme JwtBearerDefaults.AuthenticationScheme. Additional authentication has to be registered with a unique authentication scheme.
Also it rewrites default policy in services.AddAuthorization() insted of services.AddControllers()
In case anyone else experiences this issue, to sort out the problem you need to include the Authorized Schemes as an attribute on each controller. Then everything is works tickety-boo.
E.g.
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme + "," + ApiKeyAuthenticationOptions.DefaultScheme)]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : BaseAuthenticatedController
{
I'm trying to configure an authentication in some application that will consume the login validation from another system. Basically, I get a token with the users information, and I have to map it to my database, because the user it was already authenticated. We're doing it with using jwt tokens.
So here's the problem:
The token I'm getting doesn't have "iat" field, and AspNetCore seems to reject the token without that field.
Is there a way to configure the authentication to ignore that field?
Here is the token structure:
TOKEN - HEADER
{
"alg": "HS512"
}
TOKEN - BODY
{
"sub": [mysub],
"user": { ... },
"exp": [timestamp]
}
And here's the configuration:
...
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuerSigningKey = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
...
Edit: An earlier version of this answer mixed up iat and nbf. The answer has been rewritten accordingly.
I tried reproducing your issue in an empty project, and was successfully able to validate a token with the structure you outlined in your question (so without the iat claim).
Setup I used to get this to work:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = false,
ValidateIssuer = false,
ValidateAudience = false,
SignatureValidator = (t, p) => new JwtSecurityToken(t)
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
[Authorize]
[Route("debug")]
public class DebugAuthController : ControllerBase
{
[HttpGet]
public IActionResult Get() => Ok(User.Claims.Single(c => c.Type == "user").Value);
}
I used the following token for testing: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJteXN1YmplY3QiLCJ1c2VyIjp7Im5hbWUiOiJTdGFja092ZXJmbG93In0sImV4cCI6MTU5MDk5NzMyNn0.FVFl6gDYOrmzj7_6OqHPTxU3mfQWs864u7fBLM5ThuM
It's worth double-checking to see if you're calling both UseAuthentication and UseAuthorization in ConfigureServices, and that you're calling them in that order.
Note: Sample code provided disables virtually all validation checks on the JWT for testing purposes. Do not use this code as-is unless you know what you're doing!
I have a .NET Core 2.1 Web API application in which I have Azure AD set up for authentication. For my authorization I'm using an AuthorizationHandler that does some validation based on the user name. The problem I'm running into is that the User.Identity.Name always returns null and I'm not sure why.
Here's my Startup.cs where I have the Authentication and Authorization set up :
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors("AllowAnyOrigin");
app.UseAuthentication();
app.UseMvc();
}
public void ConfigureServices(IServiceCollection services)
{
// Azure AD
services.AddAuthentication(
sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(
options =>
{
options.Authority = "https://login.microsoftonline.com/" + "MyTenant";
options.Audience = "MyClientId";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://login.microsoftonline.com/" + "MyTenant" +"/v2.0";
};
});
services.AddAuthorization(
options =>
{
options.AddPolicy("MyPolicy", policy => policy.Requirements.Add(new NameRequirement());
});
services.AddSingleton<IAuthorizationHandler, NameRequirementHandler>();
services.AddCors(options =>
{
options.AddPolicy("AllowAnyOrigin",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.Configure<MvcOptions>(options => {
options.Filters.Add(new CorsAuthorizationFilterFactory("AllowAnyOrigin"));
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
In my my AuthorizationHandler I want to get the name of the authenticated user in order to do some validation on it. I can see the Bearer token in the Request however the User.Identity.Name and all of the claims are null.
public class NameRequirementHandler : AuthorizationHandler<NameRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, NameRequirement requirement)
{
var authorizationFilterContext = context.Resource as AuthorizationFilterContext;
if (authorizationFilterContext != null)
{
HttpContext httpContext = authorizationFilterContext.HttpContext;
string userName = httpContext.User.Identity.Name; // ALWAYS NULL
//Do some validation here with the user name value
}
context.Succeed(requirement);
return Task.CompletedTask;
}
}
Currently I have a really simple Controller that I'm using to test the Authentication and Authorization:
[Authorize(Policy = "MyPolicy")]
public class ValuesController
{
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
}
What am I missing in order to populate the user information from the Bearer token? To add a little more context, I'm porting this over from .NET Framework and it works there but it uses the extension method UseWindowsAzureActiveDirectoryBearerAuthentication which doesn't exist in .NET Core
Here's what it looks like in .NET Framework
public void Configuration(IAppBuilder app)
{
var tokenValidation = new TokenValidationParameters
{
ValidAudience = "https://graph.windows.net/"
};
var authOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = "MyTenant",
TokenValidationParameters = tokenValidation,
MetadataAddress = ""
};
app.UseWindowsAzureActiveDirectoryBearerAuthentication(authOptions);
}
I've seen other questions posted and read many articles but still haven't been able to get this to work. What part of my configuration is wrong?
Thanks in advance.
UPDATED
I ended up finding the solution to this issue, the audience value was incorrectly set. I was not setting the value of the audience that the token's "aud" value. You can go to https://jwt.ms to see the claims of the token and make sure the right audience is set.
You need to call UseAuthentication in the Configure method where you have access to IApplicationBuilder. It'll be something like this,
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseAuthentication(); // Make sure you've done this!
app.UseMvc();
}
From the documentation, "Adds the AuthenticationMiddleware to the specified IApplicationBuilder, which enables authentication capabilities."
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.authappbuilderextensions.useauthentication?view=aspnetcore-2.0
I am trying to get started with authentication on an ASP.NET Core 2.0 web app.
My company is using Ping Federate and I am trying to authenticate my users using the company login page and in return validating the returned token using my signing key (X509SecurityKey down here).
The login page link looks like:
https://companyname.com/authorization.oauth2?response_type=code&redirect_uri=https%3a%2f%2fJWTAuthExample%2fAccount%2fLogin&client_id=CompanyName.Web.JWTAuthExample&scope=&state=<...state...>
Out of the box, I configured the Startup.cs to be able to log in and challenge against this site.
I decorated my HomeController with a [Authorize(Policy="Mvc")] but when I access one of the pages, I just get a blank page.
Debug is not hitting the OnChallenge or OnAuthenticationFailed methods when I add it to options.Events (I think because user needs to be authenticated first).
So, what am I missing in order for a redirect to my authentication website to happen? Is it built in or do I have to do some manual configuration?
(Note: In other web apps, using asp net framework, I use a redirect in an Authorize attribute when authentication fails)
Related post: Authorize attribute does not redirect to Login page when using .NET Core 2's AddJwtBearer
- From this post, does it mean I am not using the right authentication method? I am building a web app, not an API.
namespace JWTAuthExample
{
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
Configuration = configuration;
HostingEnvironment = hostingEnvironment;
string certificatepath = Path.Combine(HostingEnvironment.ContentRootPath, $"App_Data\\key.cer");
KEY = new X509SecurityKey(new X509Certificate2(certificatepath));
}
public IConfiguration Configuration { get; }
public IHostingEnvironment HostingEnvironment { get; }
private string AUTH_LOGINPATH { get; } = Configuration["DefaultAuth:AuthorizationEndpoint"];
private X509SecurityKey KEY { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.IncludeErrorDetails = true;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
// Ensure token expiry
RequireExpirationTime = true,
ValidateLifetime = true,
// Ensure token audience matches site audience value
ValidateAudience = false,
ValidAudience = AUTH_LOGINPATH,
// Ensure token was issued by a trusted authorization server
ValidateIssuer = true,
ValidIssuer = AUTH_LOGINPATH,
// Specify key used by token
RequireSignedTokens = true,
IssuerSigningKey = KEY
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Mvc", policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
Following Brad's suggestion,
Here is a sample of code to perform an OpenId Connect confirguration on ASP NET 2.0
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = Configuration["AuthoritySite"];
options.ClientId = Configuration["ClientId"];
options.ClientSecret = Configuration["ClientSecret"];
options.Scope.Clear();
// options.Scope.Add("Any:Scope");
options.ResponseType = OpenIdConnectResponseType.CodeIdTokenToken;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.TokenValidationParameters = new TokenValidationParameters
{
// Compensate server drift
ClockSkew = TimeSpan.FromHours(12),
// Ensure key
IssuerSigningKey = CERTIFICATE,
// Ensure expiry
RequireExpirationTime = true,
ValidateLifetime = true,
// Save token
SaveSigninToken = true
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Mvc", policy =>
{
policy.AuthenticationSchemes.Add(OpenIdConnectDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
}
More details here: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1