Esempio n. 1
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // *** CHANGE THIS FOR PRODUCTION USE ***
            // Here, we're generating a random key to sign tokens - obviously this means
            // that each time the app is started the key will change, and multiple servers
            // all have different keys. This should be changed to load a key from a file
            // securely delivered to your application, controlled by configuration.
            //
            // See the RSAKeyUtils.GetKeyParameters method for an examle of loading from
            // a JSON file.
            RSAParameters keyParams = RsaKeyService.GetRandomKey();

            // Create the key, and a set of token options to record signing credentials
            // using that key, along with the other parameters we will need in the
            // token controlller.
            key          = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(keyParams);
            tokenOptions = new TokenOptionsModel()
            {
                Audience           = TokenAudience,
                Issuer             = TokenIssuer,
                SigningCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(key, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.RsaSha256Signature)
            };

            // Save the token options into an instance so they're accessible to the
            // controller.
            services.AddSingleton <TokenOptionsModel>(tokenOptions);

            // Enable the use of an [Authorize("Bearer")] attribute on methods and classes to protect.
            services.AddAuthorization(auth =>
            {
                // inline policies
                //https://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/
                auth.AddPolicy("Admin", new AuthorizationPolicyBuilder()
                               .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                               .RequireAuthenticatedUser().RequireClaim("Admin").Build());

                // inline policies
                //https://leastprivilege.com/2015/10/12/the-state-of-security-in-asp-net-5-and-mvc-6-authorization/
                auth.AddPolicy("Manager", new AuthorizationPolicyBuilder()
                               .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                               .RequireAuthenticatedUser().RequireClaim("Manager").Build());

                //https://github.com/mrsheepuk/ASPNETSelfCreatedTokenAuthExample
                auth.DefaultPolicy = new AuthorizationPolicyBuilder()
                                     .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                                     .RequireAuthenticatedUser().Build();
            });

            // CORS works but hosting can make things confusing
            // http://stackoverflow.com/questions/34212765/how-do-i-get-the-kestrel-web-server-to-listen-to-non-localhost-requests
            services.AddCors(o => o.AddPolicy("AnyOrigin", builder =>
            {
                builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader();
            }));

            // Add framework services.
            services.AddMvc();
        }
Esempio n. 2
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext <IdentityDbContext>(options =>
                                                      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity <IdentityUser, Role>()
            .AddEntityFrameworkStores <IdentityDbContext>()
            .AddDefaultTokenProviders();

            services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents       = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents     = true;
                options.Events.RaiseSuccessEvents     = true;
            })
                          .AddInMemoryIdentityResources(Configuration.GetSection("IdentityResources").Get <List <IdentityResource> >())
                          .AddInMemoryApiResources(Configuration.GetSection("ApiResources").Get <List <ApiResource> >())
                          .AddInMemoryClients(Configuration.GetSection("IdentityServer:Clients"))
                          .AddAspNetIdentity <IdentityUser>()
                          .AddOperationalStore(options =>
            {
                options.RedisConnectionString = Configuration.GetConnectionString("RedisConnection");
            });

            var rsa = new RsaKeyService(Configuration["SigningCredentialFilePath"], TimeSpan.FromDays(30));

            services.AddTransient(provider => rsa);
            builder.AddSigningCredential(rsa.GetKey());

            services.AddAuthentication()
            .AddGoogle("Google", options =>
            {
                var googleAuth       = Configuration.GetSection("GoogleAuth");
                options.ClientId     = googleAuth["Id"];
                options.ClientSecret = googleAuth["Secret"];
            });
        }
Esempio n. 3
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            _identityConfig   = Config.GetIdentityResources();
            _apiConfig        = Config.GetApiResources(Configuration);
            _clientConfig     = Config.GetClients(Configuration);
            _publicOrigin     = Config.GetPublicOrigin(Configuration);
            _cookieExpiration = Config.GetCookieExpirationByMinute(Configuration);

            var encConnStrMySql = Configuration.GetConnectionString("MySqlConnection(Azure)");
            var connStrMySql    = AesCryptoUtil.Decrypt(encConnStrMySql);

            Log.Information($"Connection String: {connStrMySql}");

            services.AddDbContext <ApplicationDbContext>(option =>
                                                         option.UseMySQL(connStrMySql));

            services.AddIdentity <ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores <ApplicationDbContext>()
            .AddDefaultTokenProviders();

            services.AddCors(options =>
            {
                options.AddPolicy(EmpWebOrigins, corsBuilder =>
                {
                    corsBuilder
                    .AllowAnyHeader()
                    // .WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
                    // .AllowAnyOrigin()
                    .WithOrigins(
                        _clientConfig.First().AllowedCorsOrigins.ToArray()
                        )
                    .AllowAnyMethod()
                    // .WithMethods("GET", "PUT", "POST", "DELETE")
                    .AllowCredentials();
                });
            });

            services.AddMvc();
            services.AddTransient <IProfileService, CustomProfileService>();

            var builder = services.AddIdentityServer(options => {
                options.Events.RaiseErrorEvents               = true;
                options.Events.RaiseInformationEvents         = true;
                options.Events.RaiseFailureEvents             = true;
                options.Events.RaiseSuccessEvents             = true;
                options.Authentication.CheckSessionCookieName = "IDS4_EMP.Sts";
                options.PublicOrigin = _publicOrigin;
            })
                          .AddInMemoryIdentityResources(_identityConfig)
                          .AddInMemoryApiResources(_apiConfig)
                          .AddInMemoryClients(_clientConfig)
                          .AddAspNetIdentity <ApplicationUser>()
                          .AddProfileService <CustomProfileService>();

            services.ConfigureApplicationCookie(options => {
                // To prevent Refresh Access Token overriding cookie refreshe, subtract 1 minute
                options.ExpireTimeSpan      = TimeSpan.FromMinutes(_cookieExpiration - 1);
                options.SlidingExpiration   = true;
                options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
            });

            if (_env.IsDevelopment())
            {
                // builder.AddDeveloperSigningCredential();
                var rsa = new RsaKeyService(_env, TimeSpan.FromDays(30), Configuration);
                services.AddSingleton <RsaKeyService>(provider => rsa);
                builder.AddSigningCredential(rsa.GetKey());
            }
            else
            {
                var rsa = new RsaKeyService(_env, TimeSpan.FromDays(30), Configuration);
                services.AddSingleton <RsaKeyService>(provider => rsa);
                builder.AddSigningCredential(rsa.GetKey());

                // services.AddIdentityServer(...).AddSigningCredential(new X509Certificate2(bytes, "password")
                // builder.AddSigningCredential(new X509Certificate2(bytes, "password");
            }
        }
Esempio n. 4
0
        /// <summary>
        /// This optional method gets called by the runtime. Use this method to add services to the container.
        /// </summary>
        /// <param name="services">IServiceCollection</param>
        /// <method>ConfigureServices(IServiceCollection services)</method>
        public void ConfigureServices(IServiceCollection services)
        {
            // Register appsettings.json
            AppSettings appSettings = new AppSettings();

            _configuration.Bind("AppSettings", appSettings);
            _appSettings = appSettings;
            services.AddSingleton(_appSettings);

            services.AddMvc();
            services.AddControllersWithViews();

            // Register IHttpContextAccessor
            services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            // Register controller fillters
            services.AddScoped <SecurityHeadersAttribute>();
            services.AddScoped <ControllerActionLogFilter>();
            services.AddScoped <ControllerActionUserFilter>();
            services.AddScoped <ControllerActionPageFilter>();

            // Register RsaKeyService
            var rsa = new RsaKeyService(_webHostEnvironment, TimeSpan.FromDays(30));

            services.AddSingleton <RsaKeyService>(provider => rsa);

            services.AddCustomUserStore(options =>
            {
                options.ISDBaseUrl     = appSettings.Application.ISDUrlTrim;
                options.ApiBaseUrl     = appSettings.Application.ApiUrlTrim;
                options.ApiAccessToken = Config.ApiAccessToken;
            });

            services.AddCustomRoleStore(options =>
            {
                options.ISDBaseUrl     = appSettings.Application.ISDUrlTrim;
                options.ApiBaseUrl     = appSettings.Application.ApiUrlTrim;
                options.ApiAccessToken = Config.ApiAccessToken;
            });

            services.AddEmailService(options =>
            {
                options.Host        = _appSettings.EmailService.Host;
                options.Port        = _appSettings.EmailService.Port;
                options.EnableSsl   = _appSettings.EmailService.EnableSsl;
                options.Credentials = new NetworkCredential(
                    _appSettings.EmailService.UserId,
                    _appSettings.EmailService.Password);
            });

            services.AddIdentity <ApplicationUser, ApplicationRole>()
            .AddUserStore <CustomUserStore>()
            .AddRoleStore <CustomRoleStore>()
            .AddUserManager <CustomUserManager>()
            .AddDefaultTokenProviders();

            services.Configure <DataProtectionTokenProviderOptions>(
                x => x.TokenLifespan = TimeSpan.FromMinutes(15)
                );

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents       = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents     = true;
                options.Events.RaiseSuccessEvents     = true;

                options.EmitStaticAudienceClaim = true;

                options.KeyManagement.RotationInterval  = TimeSpan.FromDays(15);
                options.KeyManagement.PropagationTime   = TimeSpan.FromDays(2);
                options.KeyManagement.RetentionDuration = TimeSpan.FromDays(3);
            })
                          .AddAspNetIdentity <ApplicationUser>();

            // in-memory, code config
            builder.AddInMemoryIdentityResources(Config.IdentityResources);
            builder.AddInMemoryApiScopes(Config.ApiScopes);
            builder.AddInMemoryClients(Config.Clients);

            // not recommended for production - you need to store your key material somewhere secure
            // builder.AddDeveloperSigningCredential();

            // Duende IdentityServer defaults to automatic key management
            // see: https://docs.duendesoftware.com/identityserver/v5/fundamentals/keys/
            //RsaSecurityKey key = rsa.GetKey();
            //builder.AddValidationKey(key);
            //builder.AddSigningCredential(key, SecurityAlgorithms.RsaSha512);

            services.AddAuthentication()
            .AddMicrosoftAccount("Microsoft", microsoftOptions =>
            {
                microsoftOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                microsoftOptions.ClientId     = appSettings.Authentication.Microsoft.ClientId;
                microsoftOptions.ClientSecret = appSettings.Authentication.Microsoft.ClientSecret;
            })
            .AddGoogle("Google", googleOptions =>
            {
                googleOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                googleOptions.ClientId     = appSettings.Authentication.Google.ClientId;
                googleOptions.ClientSecret = appSettings.Authentication.Google.ClientSecret;
            })
            .AddGitHub("GitHub", githubOptions =>
            {
                githubOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                githubOptions.ClientId     = appSettings.Authentication.GitHub.ClientId;
                githubOptions.ClientSecret = appSettings.Authentication.GitHub.ClientSecret;
            })
            .AddTwitter("Twitter", twitterOptions =>
            {
                twitterOptions.SignInScheme        = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                twitterOptions.ConsumerKey         = appSettings.Authentication.Twitter.ConsumerAPIKey;
                twitterOptions.ConsumerSecret      = appSettings.Authentication.Twitter.ConsumerSecret;
                twitterOptions.RetrieveUserDetails = true;
            })
            .AddFacebook("Facebook", facebookOptions =>
            {
                facebookOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                facebookOptions.AppId        = appSettings.Authentication.Facebook.AppId;
                facebookOptions.AppSecret    = appSettings.Authentication.Facebook.AppSecret;
            });

            // Override the CookieAuthenticationOptions for DefaultCookieAuthenticationScheme
            // https://github.com/IdentityServer/IdentityServer4/blob/c30de032ec1dedc3b17dfa342043850638e84b43/src/IdentityServer4/src/Configuration/DependencyInjection/ConfigureInternalCookieOptions.cs#L28
            services.Configure <CookieAuthenticationOptions>(IdentityServerConstants.DefaultCookieAuthenticationScheme, options =>
            {
                options.Cookie.SameSite     = SameSiteMode.None;
                options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
                options.Cookie.IsEssential  = true;
            });

            if (_webHostEnvironment.EnvironmentName.Equals("Production"))
            {
                services.AddHsts(options =>
                {
                    options.Preload           = true;
                    options.IncludeSubDomains = true;
                    options.MaxAge            = TimeSpan.FromDays(730);
                });

                services.AddHttpsRedirection(options =>
                {
                    options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
                    options.HttpsPort          = 443;
                });
            }
        }
Esempio n. 5
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var rsa = new RsaKeyService(_env, TimeSpan.FromDays(30));

            services.AddSingleton(provider => rsa);

            services.AddDbContext <ApplicationDbContext>(options =>
                                                         options.UseInMemoryDatabase(
                                                             Configuration.GetConnectionString("DefaultConnection")));

            var connection = Configuration["ConnectionStrings:DefaultConnection"];

            services.AddDbContext <ContextDb>(options => options.UseSqlServer(connection));

            services.AddDatabaseDeveloperPageExceptionFilter();

            services.AddDefaultIdentity <IdentityUser>(options => options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+/ ")
            .AddEntityFrameworkStores <ApplicationDbContext>();
            services.AddControllersWithViews();

            services.AddIdentityServer()
            .AddInMemoryIdentityResources(IdentityServerConfig.IdentityResources)
            .AddInMemoryApiScopes(IdentityServerConfig.ApiScopes)
            .AddInMemoryClients(IdentityServerConfig.Clients)
            .AddSigningCredential(rsa.GetKey(), RsaSigningAlgorithm.RS256);

            services
            .AddAuthentication(options =>
            {
                options.DefaultScheme          = IdentityConstants.ApplicationScheme;
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.LoginPath = new PathString("/Identity/Account/ExternalLogin");
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = IdentityConstants.ExternalScheme;
                options.SaveTokens   = true;
                options.ClientId     = Configuration["OpenIdConfig:ClientId"];
                options.Authority    = Configuration["OpenIdConfig:Issuer"];
                // The Platform MUST send the id_token via the OAuth 2 Form Post
                // See https://www.imsglobal.org/spec/security/v1p0/#successful-authentication
                options.ResponseType = OpenIdConnectResponseType.IdToken;
                // See http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html
                options.ResponseMode         = OpenIdConnectResponseMode.FormPost;
                options.Prompt               = OpenIdConnectPrompt.None;
                options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
                options.DisableTelemetry     = true;

                options.Configuration = new OpenIdConnectConfiguration
                {
                    AuthorizationEndpoint = Configuration["OpenIdConfig:AuthorizationEndpoint"],
                    TokenEndpoint         = Configuration["OpenIdConfig:TokenEndpoint"],
                    Issuer  = Configuration["OpenIdConfig:Issuer"],
                    JwksUri = Configuration["OpenIdConfig:JwksUri"]
                };

                options.CallbackPath = new PathString("/LtiTool");

                options.Scope.Clear();
                options.Scope.Add(OpenIdConnectScope.OpenId);

                options.Events = new OpenIdConnectEvents
                {
                    //OnRemoteFailure = HandleOnRemoteFailure,
                    // Authenticate the request starting at step 5 in the OpenId Implicit Flow
                    // See https://www.imsglobal.org/spec/security/v1p0/#platform-originating-messages
                    // See https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowSteps
                    OnRedirectToIdentityProvider = context =>
                    {
                        if (context.Properties.Items.TryGetValue(nameof(OidcModel.LoginHint), out var login_hint))
                        {
                            context.ProtocolMessage.LoginHint = login_hint;
                        }

                        if (context.Properties.Items.TryGetValue(nameof(OidcModel.LtiMessageHint), out var lti_message_hint))
                        {
                            context.ProtocolMessage.SetParameter("lti_message_hint", lti_message_hint);
                        }

                        if (context.Properties.Items.TryGetValue(nameof(OidcModel.ClientId), out var clientId))
                        {
                            context.ProtocolMessage.ClientId = clientId;
                        }

                        context.ProtocolMessage.Prompt = OpenIdConnectPrompt.None;

                        if (context.Properties.Items.Count < 4)
                        {
                            context.Response.Redirect("Home/Index");
                        }

                        return(Task.CompletedTask);
                    },
                };

                // Using the options.TokenValidationParameters, validate four things:
                //
                // 1. The Issuer Identifier for the Platform MUST exactly match the value of the iss
                //    (Issuer) Claim (therefore the Tool MUST previously have been made aware of this
                //    identifier.
                // 2. The Tool MUST Validate the signature of the ID Token according to JSON Web Signature
                //    RFC 7515, Section 5; using the Public Key for the Platform which collected offline.
                // 3. The Tool MUST validate that the aud (audience) Claim contains its client_id value
                //    registered as an audience with the Issuer identified by the iss (Issuer) Claim. The
                //    aud (audience) Claim MAY contain an array with more than one element. The Tool MUST
                //    reject the ID Token if it does not list the client_id as a valid audience, or if it
                //    contains additional audiences not trusted by the Tool.
                // 4. The current time MUST be before the time represented by the exp Claim;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateTokenReplay      = true,
                    ValidateAudience         = true,
                    ValidateIssuer           = true,
                    RequireSignedTokens      = true,
                    ValidateIssuerSigningKey = true,
                    ValidAudience            = Configuration["OpenIdConfig:ClientId"],
                    ValidIssuer              = Configuration["OpenIdConfig:Issuer"],
                    ValidateLifetime         = true,
                    IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) =>
                    {
                        var keySetJson = new WebClient().DownloadString(Configuration["OpenIdConfig:JwksUri"]);
                        var keySet     = JsonConvert.DeserializeObject <JsonWebKeySet>(keySetJson);
                        var key        = keySet.Keys.SingleOrDefault(k => k.Kid == kid);

                        return(new List <JsonWebKey> {
                            key
                        });
                    },
                    ClockSkew = TimeSpan.FromMinutes(5.0)
                };
            });

            services.AddSingleton(Configuration.GetSection("OpenIdConfig").Get <OidcModel>());

            // Make AccessTokenService available for dependency injection.
            services.AddTransient <AccessTokenService>();
        }
Esempio n. 6
0
        public void ConfigureServices(IServiceCollection services)
        {
            //IdentityModelEventSource.ShowPII = true; // Better Identity stacktraces and messages. (Insecure)
            services.AddDatabaseDeveloperPageExceptionFilter();
            services.AddControllersWithViews();

            services.AddDbContext <ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity <ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores <ApplicationDbContext>()
            .AddDefaultTokenProviders();

            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents       = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents     = true;
                options.Events.RaiseSuccessEvents     = true;

                // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
                options.EmitStaticAudienceClaim = true;
                options.IssuerUri = Configuration["Identity:IssuerUri"];
            })
                          .AddConfigurationStore(options => // this adds the config data from DB (clients, resources)
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                                                                  sql => sql.MigrationsAssembly(migrationsAssembly));
            }) // this adds the operational data from DB (codes, tokens, consents)
                          .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                                                                  sql => sql.MigrationsAssembly(migrationsAssembly));

                options.EnableTokenCleanup   = true; // this enables automatic token cleanup. this is optional.
                options.TokenCleanupInterval = 30;
            })
                          .AddAspNetIdentity <ApplicationUser>()
                          .AddProfileService <ProfileService>();

            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                var rsa = new RsaKeyService(Environment, TimeSpan.FromDays(30));
                services.AddTransient <RsaKeyService>(provider => rsa);
                builder.AddSigningCredential(rsa.GetKey(), IdentityServerConstants.RsaSigningAlgorithm.RS512);
            }

            services.AddAuthentication()
            .AddGoogle(options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                // register your IdentityServer with Google at https://console.developers.google.com
                // enable the Google+ API
                // set the redirect URI to http://identity:5000/signin-google
                options.ClientId     = Configuration["Identity:Google:ClientId"];
                options.ClientSecret = Configuration["Identity:Google:ClientSecret"];
            });

            services.AddSendGrid(options => // Use whatever email provider you want to. I use SendGrid, because it has a basic free plan to get started with.
            {
                options.ApiKey = Configuration["SendGridApiKey"];
            });

            services.AddTransient <IEmailService, EmailService>();
        }
 /// <summary>
 /// Create an instance of the AccessTokenService.
 /// </summary>
 /// <param name="context">The application database context to look up the issuer's token endpoint.</param>
 /// <param name="httpClientFactory">The HttpClient factory.</param>
 /// <param name-"rsaKeyService">RSA Key service</param>
 public AccessTokenService(IHttpClientFactory httpClientFactory, OidcModel oidcModel, RsaKeyService rsaKeyService)
 {
     _httpClientFactory = httpClientFactory;
     _oidcModel         = oidcModel;
     _rsaKeyService     = rsaKeyService;
 }