private static void AddJwtBearerAuthentication(IAppBuilder app, OktaWebApiOptions options) { var issuer = UrlHelper.CreateIssuerUrl(options.OktaDomain, options.AuthorizationServerId); var httpClient = new HttpClient(new UserAgentHandler("okta-aspnet", typeof(OktaMiddlewareExtensions).Assembly.GetName().Version)); var configurationManager = new ConfigurationManager <OpenIdConnectConfiguration>( issuer + "/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever(httpClient)); // Stop the default behavior of remapping JWT claim names to legacy MS/SOAP claim names JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); var signingKeyProvider = new DiscoveryDocumentSigningKeyProvider(configurationManager); var tokenValidationParameters = new DefaultTokenValidationParameters(options, issuer) { ValidAudience = options.Audience, IssuerSigningKeyResolver = (token, securityToken, keyId, validationParameters) => { var signingKeys = signingKeyProvider.GetSigningKeysAsync().GetAwaiter().GetResult(); return(signingKeys.Where(x => x.KeyId == keyId)); }, // CLIST: 2019-11-08 - save the claims token into the bootstrap context for k2 SaveSigninToken = true, }; app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, TokenValidationParameters = tokenValidationParameters, TokenHandler = new StrictTokenHandler(), }); }
public void FailWhenAuhtorizationServerIdNullOrEmpty(string autorizationServer) { var options = new OktaWebApiOptions() { OktaDomain = ValidOktaDomain, AuthorizationServerId = autorizationServer, }; Action action = () => new OktaWebApiOptionsValidator().Validate(options); action.Should().Throw <ArgumentException>().Where(e => e.ParamName == nameof(OktaWebApiOptions.AuthorizationServerId)); }
public static IAppBuilder UseOktaWebApi(this IAppBuilder app, OktaWebApiOptions options) { if (app == null) { throw new ArgumentNullException(nameof(app)); } new OktaWebApiOptionsValidator().Validate(options); AddJwtBearerAuthentication(app, options); return(app); }
public void NotFailWhenAuhtorizationServerIsNotNullOrEmpty(string autorizationServer) { var options = new OktaWebApiOptions() { OktaDomain = ValidOktaDomain, }; // The default AS is `default`, no exceptions expected. Action action = () => new OktaWebApiOptionsValidator().Validate(options); action.Should().NotThrow(); options = new OktaWebApiOptions() { OktaDomain = ValidOktaDomain, AuthorizationServerId = autorizationServer, }; action = () => new OktaWebApiOptionsValidator().Validate(options); action.Should().NotThrow(); }
private static AuthenticationBuilder AddJwtValidation(AuthenticationBuilder builder, OktaWebApiOptions options) { var issuer = UrlHelper.CreateIssuerUrl(options.OktaDomain, options.AuthorizationServerId); var tokenValidationParameters = new DefaultTokenValidationParameters(options, issuer) { ValidAudience = options.Audience, }; builder.AddJwtBearer(opt => { opt.Audience = options.Audience; opt.Authority = issuer; opt.TokenValidationParameters = tokenValidationParameters; opt.BackchannelHttpHandler = new UserAgentHandler("okta-aspnetcore", typeof(OktaAuthenticationOptionsExtensions).Assembly.GetName().Version); opt.SecurityTokenValidators.Clear(); opt.SecurityTokenValidators.Add(new StrictSecurityTokenValidator()); }); return(builder); }
public static AuthenticationBuilder AddOktaWebApi(this AuthenticationBuilder builder, OktaWebApiOptions options) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } new OktaWebApiOptionsValidator().Validate(options); return(AddJwtValidation(builder, options)); }
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.AllowAnyHeader(); policy.AllowAnyMethod(); policy.WithOrigins( "http://localhost:8080" ); policy.WithExposedHeaders( "X-Pagination-Total", "X-Pagination-PageCount", "X-Pagination-PageSize", "X-Pagination-Page", "X-Pagination-HasPrevious", "X-Pagination-HasNext"); }); }); services.AddDataAccess(Configuration); services.AddServices(Configuration); services.AddAmazonServices(Configuration); services.AddAutoMapper(typeof(MappingProfile)); var oktaDomain = Configuration["Okta:OktaDomain"]; services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { var issuer = $"{oktaDomain}/oauth2/default"; var oktaOptions = new OktaWebApiOptions(); var tokenValidationParams = new DefaultTokenValidationParameters(oktaOptions, issuer) { ValidAudience = oktaOptions.Audience }; options.Authority = issuer; options.Audience = oktaOptions.Audience; options.SecurityTokenValidators.Clear(); options.SecurityTokenValidators.Add(new StrictSecurityTokenValidator()); options.Events = new JwtBearerEvents { OnTokenValidated = async context => { // TODO: Replace with service var userEmail = context.Principal.FindFirstValue(ClaimTypes.NameIdentifier); var userRepository = context.HttpContext.RequestServices.GetRequiredService <IRepository <User> >(); var user = await userRepository.TableNoTracking.FirstOrDefaultAsync(x => x.EmailAddress == userEmail); if (user != null) { var appClaims = new List <Claim> { new Claim(AppClaimTypes.UserId, user.Id.ToString(CultureInfo.InvariantCulture), null, AppClaimTypes.AppClaimsIssuer), }; var appIdentity = new ClaimsIdentity(appClaims); context.Principal.AddIdentity(appIdentity); } } }; }); // Policies are defined in ServiceCollectionExtensions.AddServices() services.AddAuthorization(); services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "RailWiki API", Version = "v1" }); // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); options.IncludeXmlComments(xmlPath); options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, OpenIdConnectUrl = new Uri($"{oktaDomain}/oauth2/default/v1/.well-known/openid-configuration"), Flows = new OpenApiOAuthFlows { Implicit = new OpenApiOAuthFlow { AuthorizationUrl = new Uri($"{oktaDomain}/oauth2/default/v1/authorize"), TokenUrl = new Uri($"{oktaDomain}/oauth2/default/v1/token"), Scopes = new Dictionary <string, string> { { "openid", "" }, { "profile", "" } } } } }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } }, new[] { "read" } } }); }); }