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();
        }
Example #5
0
        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);
        }
Example #6
0
        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));
        }
Example #7
0
        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" }
                    }
                });
            });
        }