public async Task<string> Index()
        {
            try
            {
                string username = ConfigurationManager.AppSettings["Weee.WarmUpUserUsername"];
                string password = ConfigurationManager.AppSettings["Weee.WarmUpUserPassword"];

                if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
                {
                    return "Skipping warm-up - No user details provided.";
                }

                Stopwatch stopwatch = Stopwatch.StartNew();

                string baseUrl = ConfigurationManager.AppSettings["Weee.SiteRoot"];
                string clientId = ConfigurationManager.AppSettings["Weee.ApiClientID"];
                string clientSecret = ConfigurationManager.AppSettings["Weee.ApiSecret"];

                // Fetch an access token for the warm-up user.
                IOAuthClient client = new OAuthClient(baseUrl, clientId, clientSecret);
                var tokenResponse = await client.GetAccessTokenAsync(username, password);

                if (tokenResponse.AccessToken == null)
                {
                    if (tokenResponse.IsHttpError)
                    {
                        throw new Exception(string.Format("Request for access token returned HttpError: Status - {0}, Reason - {1}, Error - {2}",
                            tokenResponse.HttpErrorStatusCode, tokenResponse.HttpErrorReason, tokenResponse.Error));
                    }
                    else if (tokenResponse.IsError)
                    {
                        throw new Exception(string.Format("Request for access token returned Error: {0}", tokenResponse.Error));
                    }
                    else
                    {
                        throw new Exception("Request for access token returned null.");
                    }
                }

                // Fetch the user info for the warm-up user.
                IUserInfoClient userInfoClient = new UserInfoClient(baseUrl);
                var userInfo = await userInfoClient.GetUserInfoAsync(tokenResponse.AccessToken);

                return string.Format("Warm-up complete in {0} seconds.", stopwatch.Elapsed.TotalSeconds);
            }
            catch (Exception ex)
            {
                throw new Exception("API warm-up failed.", ex);
            }
        }
예제 #2
0
        // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app, IConfigSource config)
        {
            // Configure the db context, user manager and signin manager to use a single instance per request
            app.CreatePerOwinContext(MissionLineDbContext.Create);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            NameValueCollection configStrings = ConfigurationManager.AppSettings;

            app.Use <NonceCleanupOpenIdConnectAuthenticationMiddleware>(app, new OpenIdConnectAuthenticationOptions
            {
                Authority    = configStrings["auth:authority"].Trim('/') + "/",
                ClientId     = configStrings["auth:clientId"],
                RedirectUri  = configStrings["auth:redirect"].Trim('/') + "/",
                ResponseType = "code id_token token",
                Scope        = "openid email profile database-api kcsara-profile",
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name"
                },
                SignInAsAuthenticationType = "Cookies",
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            configStrings["auth:authority"].Trim('/') + "/connect/token",
                            configStrings["auth:clientId"],
                            configStrings["auth:secret"]);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
                            n.Code, n.RedirectUri);

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(
                            new Uri(configStrings["auth:authority"].Trim('/') + "/connect/userinfo"),
                            tokenResponse.AccessToken);

                        var userInfoResponse = await userInfoClient.GetAsync();

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        if (!string.IsNullOrWhiteSpace(tokenResponse.RefreshToken))
                        {
                            id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        }
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
        public void Configuration(IAppBuilder app)
        {
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = "katanaclient",
                Authority             = Constants.BaseAddress,
                RedirectUri           = "http://localhost:2672/",
                PostLogoutRedirectUri = "http://localhost:2672/",
                ResponseType          = "code id_token token",
                Scope = "openid email profile read write offline_access",

                SignInAsAuthenticationType = "Cookies",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // filter "protocol" claims
                        var claims = new List <Claim>(from c in n.AuthenticationTicket.Identity.Claims
                                                      where c.Type != "iss" &&
                                                      c.Type != "aud" &&
                                                      c.Type != "nbf" &&
                                                      c.Type != "exp" &&
                                                      c.Type != "iat" &&
                                                      c.Type != "nonce" &&
                                                      c.Type != "c_hash" &&
                                                      c.Type != "at_hash"
                                                      select c);

                        // get userinfo data
                        var userInfoClient = new UserInfoClient(
                            new Uri(Constants.UserInfoEndpoint),
                            n.ProtocolMessage.AccessToken);

                        var userInfo = await userInfoClient.GetAsync();
                        userInfo.Claims.ToList().ForEach(ui => claims.Add(new Claim(ui.Item1, ui.Item2)));

                        // get access and refresh token
                        var tokenClient = new OAuth2Client(
                            new Uri(Constants.TokenEndpoint),
                            "katanaclient",
                            "secret");

                        var response = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                        claims.Add(new Claim("access_token", response.AccessToken));
                        claims.Add(new Claim("expires_at", DateTime.Now.AddSeconds(response.ExpiresIn).ToLocalTime().ToString()));
                        claims.Add(new Claim("refresh_token", response.RefreshToken));
                        claims.Add(new Claim("id_token", n.ProtocolMessage.IdToken));

                        n.AuthenticationTicket = new AuthenticationTicket(new ClaimsIdentity(claims.Distinct(new ClaimComparer()), n.AuthenticationTicket.Identity.AuthenticationType), n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = async n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
                            n.ProtocolMessage.IdTokenHint = idTokenHint;
                        }
                    },
                }
            });
        }
        public static void Config(IAppBuilder app, string identityServerUrl)
        {
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();
            AntiForgeryConfig.UniqueClaimTypeIdentifier = IdentityModel.JwtClaimTypes.Name;

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority          = identityServerUrl + "/identity",
                AuthenticationType = "oidc",
                ClientId           = "ClientId",
                ClientSecret       = "ClientSecret",
                Scope        = "openid profile email roles WebAPI",
                ResponseType = "id_token token",
                RedirectUri  = identityServerUrl,
                SignInAsAuthenticationType = "Cookies",
                UseTokenLifetime           = false,
                //CallbackPath = new PathString(identityServerUrl + "/identity"),
                //CallbackPath = new PathString("/callback/"),
                //CallbackPath = new PathString("/Home"),
                ProtocolValidator = new OpenIdConnectProtocolValidator
                {
                    RequireNonce = true
                },

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var nid = new ClaimsIdentity(
                            n.AuthenticationTicket.Identity.AuthenticationType,
                            Constants.ClaimTypes.GivenName,
                            Constants.ClaimTypes.Role);

                        // get userinfo data
                        var endpoint       = n.Options.Authority + "/connect/userinfo";
                        var userInfoClient = new UserInfoClient(endpoint);

                        var userInfo = await userInfoClient.GetAsync(n.ProtocolMessage.AccessToken);
                        userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Type, ui.Value)));

                        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = context =>
                    {
                        var appBaseUrl  = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
                        var queryString = context.Request.Uri.PathAndQuery;
                        context.ProtocolMessage.RedirectUri = appBaseUrl + queryString;

                        if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
                        {
                            context.ProtocolMessage.RedirectUri = identityServerUrl;
                            return(Task.FromResult(0));
                        }

                        if (context.ProtocolMessage.RequestType != OpenIdConnectRequestType.LogoutRequest)
                        {
                            return(Task.FromResult(0));
                        }
                        var idTokenHint = context.OwinContext.Authentication.User.FindFirst("id_token");

                        if (idTokenHint != null)
                        {
                            context.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                        }

                        return(Task.FromResult(0));
                    },

                    AuthenticationFailed = context =>
                    {
                        if (context.Exception is OpenIdConnectProtocolInvalidNonceException)
                        {
                            context.SkipToNextMiddleware();
                            return(Task.FromResult(0));
                        }

                        if (!context.OwinContext.Authentication.User.Identity.IsAuthenticated)
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/");
                            return(Task.FromResult(0));
                        }
                        context.HandleResponse();
                        context.Response.Redirect("/ValidatorError?message=" + context.Exception.Message);
                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #5
0
        public void Configuration(IAppBuilder app)
        {
            // for the mvc app
            AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority = "https://localhost:44304/identity",

                ClientId     = "mvc",
                RedirectUri  = "https://localhost:44302/",
                ResponseType = "id_token token",
                Scope        = "openid profile roles sampleApi",

                SignInAsAuthenticationType = "Cookies",
                // UseTokenLifetime = false,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var id = n.AuthenticationTicket.Identity;

                        var nid = new ClaimsIdentity(id.AuthenticationType, Constants.ClaimTypes.GivenName, Constants.ClaimTypes.Role);

                        // claims to keep
                        //var givenName = id.FindFirst(Constants.ClaimTypes.GivenName);
                        //var familyName = id.FindFirst(Constants.ClaimTypes.FamilyName);
                        //var sub = id.FindFirst(Constants.ClaimTypes.Subject);
                        //var roles = id.FindAll(Constants.ClaimTypes.Role);

                        //nid.AddClaim(givenName);
                        //nid.AddClaim(familyName);
                        //nid.AddClaim(sub);
                        //nid.AddClaims(roles);

                        var userInfoClient = new UserInfoClient(
                            new Uri(n.Options.Authority + "/connect/userinfo"),
                            n.ProtocolMessage.AccessToken);

                        var userInfo = await userInfoClient.GetAsync();
                        userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Item1, ui.Item2)));

                        nid.AddClaim(new Claim(Constants.TokenTypes.IdentityToken, n.ProtocolMessage.IdToken));
                        nid.AddClaim(new Claim(Constants.TokenTypes.AccessToken, n.ProtocolMessage.AccessToken));
                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
                    },
                    RedirectToIdentityProvider = async n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst(Constants.TokenTypes.IdentityToken).Value;
                            n.ProtocolMessage.IdTokenHint = idTokenHint;
                        }
                    }
                }
            });

            app.UseResourceAuthorization(new AuthorizationManager());


            //app.Map("/api", apiReq =>
            //    {
            //        apiReq.Use(typeof(CallApiMiddleware));
            //    });
        }
예제 #6
0
        public void Configuration(IAppBuilder app)
        {
            // Show PII information in log entries (in real app this setting should come from your app configuration source)
            // when you set this to true, you will see more details about an exception, like if the signature validation fails
            // you will see the information what key identifier was used to validate the signature of a token (otherwise you see message about PII info removed)
            // PII means: personally identifiable information
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;

            // clear the default mappings so that framework doesn't try to automatically map claims for us using its defaults
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            // Antiforgery requires this mapping/information or otherwise we will get the following error for example when trying to access visitor groups
            // A claim of type 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' or 'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' was not present on the provided ClaimsIdentity.
            // We could add those claim(s) to the user or directly configure the AntiForgeryConfig.UniqueClaimTypeIdentifier
            // here we set that antiforgery should use the 'CustomClaimNames.EpiUsername' claim value which is unique for each user in this demo
            AntiForgeryConfig.UniqueClaimTypeIdentifier = CustomClaimNames.EpiUsername; // this could be also JwtClaimTypes.Subject but then you need to remember to add that claim to the claimsidentity

            // this is not required but if you have issues with cookies then add Nuget package: Kentor.OwinCookieSaver
            // to see if that sorts out your cookie issue
            // NuGet : https://www.nuget.org/packages/Kentor.OwinCookieSaver/
            // GitHub : https://github.com/Sustainsys/owin-cookie-saver
            //app.UseKentorOwinCookieSaver();

            // set the default authentication type to 'Cookies'
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            // set the cookie auth options
            // the cookies is valid for 'configuration value here' minutes and uses sliding expiration, meaning framework will extend the validty automatically
            // see: https://docs.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.slidingexpiration?view=netframework-4.7.2
            // the OpenIdConnectAuthenticationOptions.UseTokenLifetime has to be false for this to work, if the value is true then the token lifetime will be used which is usually very short time
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                ExpireTimeSpan    = TimeSpan.FromMinutes(OIDCInMemoryConfiguration.AuthCookieValidMinutes),
                SlidingExpiration = true
            });

            // Configure the OIDC auth options
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = OIDCInMemoryConfiguration.ClientId,
                ClientSecret          = OIDCInMemoryConfiguration.ClientSecret,
                Authority             = OIDCInMemoryConfiguration.Authority,             // this should be set so that the middleware will use OIDC discovery to automatically setup endpoint configurations
                RedirectUri           = OIDCInMemoryConfiguration.WebAppOidcEndpoint,    // allowed URL to return tokens or authorization codes to, must match what has been defined for client in identity provider
                PostLogoutRedirectUri = OIDCInMemoryConfiguration.PostLogoutRedirectUrl, // allowed URL where client is allowed to be redirected after IdP logout
                Scope                     = $"openid profile email",                     // TODO: add "offline_access" scope if you need refreshtoken {CustomScopeNames.ProfileWithPermissions} {CustomScopeNames.MembershipStatus}
                ResponseType              = "code id_token",                             // hybrid flow
                RequireHttpsMetadata      = OIDCInMemoryConfiguration.RequireHttpsMetadata,
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType       = JwtClaimTypes.Name,          // change name claim name to match our demo IdP returned claim name
                    RoleClaimType       = CustomClaimNames.Permission, // change role claim name to match our demo IdP returned claim name
                    ValidateTokenReplay = true
                },
                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType, // somewhere stated that needs to be after TokenValidationParameters
                UseTokenLifetime           = false,                                           // if this is true then the token life time is used (for example IdentityServer token lifetime is 5 minutes by default) for cookie auth lifetime
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = notification =>
                    {
                        // if single site setup, the redirect url is automatically set to the page you were trying to access
                        // For example in multi-tenant setup you want to change the return url here based on the current site address
                        // See Episerver sample: https://world.episerver.com/documentation/developer-guides/CMS/security/integrate-azure-ad-using-openid-connect/
                        // and the method: HandleMultiSitereturnUrl
                        //context.ProtocolMessage.RedirectUri = "http://host-of-your-site2/the-return-page/path/here/";

                        // what kind of message are we processing
                        switch (notification.ProtocolMessage.RequestType)
                        {
                        case OpenIdConnectRequestType.Authentication:

                            if (notification.OwinContext.Response.StatusCode == 401)
                            {
                                // if the request is ajax request, like Episerver Dojo framework, don't try to redirect
                                // but return 401 so the UI will properly display the login dialog
                                if (IsAjaxRequest(notification.Request))
                                {
                                    if (Logger.IsInformationEnabled())
                                    {
                                        Logger.Information($"Request is made with AJAX and response is 401.");
                                    }

                                    notification.HandleResponse();
                                    return(Task.FromResult(0));
                                }

                                // To avoid a redirect loop to the IdP server send 403 when user is authenticated but does not have access
                                if (notification.OwinContext.Authentication.User.Identity.IsAuthenticated)
                                {
                                    if (Logger.IsInformationEnabled())
                                    {
                                        Logger.Information($"Request response code would be 401 but user '{notification.OwinContext.Authentication.User.Identity.Name}' is authenticated, switching response code to 403 (forbidden).");
                                    }

                                    notification.OwinContext.Response.StatusCode = 403;
                                    notification.HandleResponse();
                                    return(Task.FromResult(0));
                                }
                            }

                            break;

                        case OpenIdConnectRequestType.Logout:
                            // If signing out, add the id_token_hint if present
                            // see: http://openid.net/specs/openid-connect-session-1_0.html#rfc.section.5

                            if (notification.OwinContext.Authentication.User.Identity.IsAuthenticated)
                            {
                                Logger.Information($"User is logging out. User: {notification.OwinContext.Authentication.User.Identity.Name}.");
                            }

                            var idTokenHint = notification.OwinContext.Authentication.User.FindFirst(OpenIdConnectParameterNames.IdToken);

                            if (idTokenHint != null)
                            {
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.Debug($"Redirecting to Identity provider for logout with IdTokenHint.");
                                }

                                notification.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                            else
                            {
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.Debug($"Redirecting to Identity provider for logout without IdTokenHint.");
                                }
                            }

                            return(Task.FromResult(0));

                        case OpenIdConnectRequestType.Token:
                            // nothing here :D
                            break;

                        default:
                            break;
                        }

                        return(Task.FromResult(0));
                    },
                    AuthorizationCodeReceived = async notification =>
                    {
                        System.Diagnostics.Debug.WriteLine($"Authorization code received for sub: {notification.JwtSecurityToken.Subject}. Received claims: {GetClaimsAsString(notification.JwtSecurityToken.Claims)}.");

                        // show info about the claims if debug logging is enabled
                        if (Logger.IsDebugEnabled())
                        {
                            Logger.Debug($"Authorization code received for sub: {notification.JwtSecurityToken.Subject}. Received claims: {GetClaimsAsString(notification.JwtSecurityToken.Claims)}.");
                        }
                        else
                        {
                            Logger.Information($"Authorization code received for sub: {notification.JwtSecurityToken.Subject}.");
                        }

                        // config has been automatically setup using OIDC discovery because we have set the Authority value previously in when configuring OpenIdConnectAuthenticationOptions
                        OpenIdConnectConfiguration configuration = null;

                        try
                        {
                            // get OpenIdConnectConfiguration
                            configuration = await notification.Options.ConfigurationManager.GetConfigurationAsync(notification.Request.CallCancelled);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error($"Failed to get OpenIdConnectConfiguration. Cannot authorize the client with sub: {notification.JwtSecurityToken.Subject}.", ex);
                            throw;
                        }

                        // configure token client, endpoint is automatically configured using the Auto discovery: /.well-known/openid-configuration
                        var tokenClient = new TokenClient(configuration.TokenEndpoint, notification.Options.ClientId, notification.Options.ClientSecret, style: AuthenticationStyle.PostValues);

                        // exchange the authorization 'code' to access token
                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(notification.ProtocolMessage.Code, notification.RedirectUri, cancellationToken: notification.Request.CallCancelled);

                        // check if there was an error fetching the acces token
                        if (tokenResponse.IsError)
                        {
                            Logger.Error($"There was an error retrieving the access token for sub: {notification.JwtSecurityToken.Subject}. Error: {tokenResponse.Error}. Error description: {tokenResponse.ErrorDescription}.");

                            notification.HandleResponse();

                            // TODO : redirect to friendly error page
                            // does 302 redirect, but SEO is not your concern here
                            // notification.Response.Redirect("/your/nice/error/page/address/here/");

                            notification.Response.Write($"Error retrieving access token. {tokenResponse.ErrorDescription}.");
                            return;
                        }

                        if (string.IsNullOrWhiteSpace(tokenResponse.AccessToken))
                        {
                            Logger.Error($"Didn't receive access token for sub: {notification.JwtSecurityToken.Subject}.");

                            notification.HandleResponse();

                            // TODO : redirect to friendly error page
                            // does 302 redirect, but SEO is not your concern here
                            // notification.Response.Redirect("/your/nice/error/page/address/here/");

                            notification.Response.Write($"Error, access token not received. {tokenResponse.ErrorDescription}.");
                            return;
                        }

                        // sub and iss claims musta have same value when using hybrid flow (in the id token and tokenresponse)
                        // http://openid.net/specs/openid-connect-core-1_0.html#HybridIDToken2 3.3.3.6 ID Token
                        // If an ID Token is returned from both the Authorization Endpoint and from the Token Endpoint,
                        // which is the case for the response_type values "code id_token" and "code id_token token", the iss and sub Claim Values MUST be identical in both ID Tokens.

                        if (!string.IsNullOrWhiteSpace(tokenResponse.IdentityToken))
                        {
                            try
                            {
                                JwtSecurityTokenHandler idTokenHandler = new JwtSecurityTokenHandler();
                                var parsedIdToken = idTokenHandler.ReadJwtToken(tokenResponse.IdentityToken);

                                if (string.Compare(parsedIdToken.Issuer, notification.JwtSecurityToken.Issuer, StringComparison.OrdinalIgnoreCase) != 0 ||
                                    string.Compare(parsedIdToken.Subject, notification.JwtSecurityToken.Subject, StringComparison.OrdinalIgnoreCase) != 0)
                                {
                                    Logger.Error($"Authorization endpoint id token 'sub' ({notification.JwtSecurityToken.Subject}) and 'iss' ({notification.JwtSecurityToken.Issuer}) claim values don't match with token endpoint 'sub' ({parsedIdToken.Subject}) and 'iss' ({parsedIdToken.Issuer}) claim values.");

                                    notification.HandleResponse();

                                    // TODO : redirect to friendly error page
                                    // does 302 redirect, but SEO is not your concern here
                                    // notification.Response.Redirect("/your/nice/error/page/address/here/");

                                    notification.Response.Write("Token endpoint identity token doesn't match autohorization endpoint returned identity token.");
                                    return;
                                }
                            }
                            catch (Exception ex)
                            {
                                Logger.Error($"Failed to validate token endpoint identity token against autohorization endpoint returned identity token.", ex);

                                notification.HandleResponse();

                                // TODO : redirect to friendly error page
                                // does 302 redirect, but SEO is not your concern here
                                // notification.Response.Redirect("/your/nice/error/page/address/here/");

                                notification.Response.Write("Failed to validate token endpoint identity token against autohorization endpoint returned identity token.");
                                return;
                            }
                        }
                        else
                        {
                            Logger.Information($"Token endpoint didn't return identity token for sub: {notification.JwtSecurityToken.Subject}.");
                        }

                        // get userinfo using the access token
                        var userInfoClient   = new UserInfoClient(configuration.UserInfoEndpoint);
                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        // check if there was an error fetching the user information
                        if (userInfoResponse.IsError)
                        {
                            Logger.Error($"There was an error retrieving the user information for sub: {notification.JwtSecurityToken.Subject}. Error: {userInfoResponse.Error}.");

                            notification.HandleResponse();

                            // TODO : redirect to friendly error page
                            // does 302 redirect, but SEO is not your concern here
                            // notification.Response.Redirect("/your/nice/error/page/address/here/");

                            notification.Response.Write($"Error retrieving user information. {userInfoResponse.Error}.");
                            return;
                        }

                        if (Logger.IsDebugEnabled())
                        {
                            Logger.Debug($"Userinfo received for sub: {notification.JwtSecurityToken.Subject}. Received claims: {GetClaimsAsString(userInfoResponse.Claims)}.");
                        }

                        // Create a new claims identity as the automatically created claimsidentity can contain claims that we don't need
                        // and we can keep the authentication cookie size smaller this way
                        // NOTE: Episerver uses the ClaimsIdentity name claim as the username (this will be also the display name when logged in), so make sure it is unique!
                        // Other claims synched automatically are (defined in class EPiServer.Security.ClaimTypeOptions, EPiServer.Framework):
                        // Email claim: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
                        // GivenName claim: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
                        // Surname claim: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname

                        // create new claimsidentity and set name claim name to JwtClaimTypes.PreferredUserName and role claim to JwtClaimTypes.Role
                        // NOTE!: The RP MUST NOT rely upon this value being unique, as discussed in http://openid.net/specs/openid-connect-basic-1_0-32.html#ClaimStability
                        // as Episerver uses the Name claim as the username (unique) and also as the display name in edit view, we could use the sub claim but this could be a guid
                        // so for the sake of the demo I will use the JwtClaimTypes.PreferredUserName even though it is said that it can't be tusted to be unique and can contani special characters
                        // in real world cases you just need to know what claims are unique and displayable for the end user, email might be one option but then you need to check that you get it always
                        // in this demo I will always return the same username in the JwtClaimTypes.PreferredUserName as was used to login to the IdP
                        var authClaimsIdentity = new ClaimsIdentity(notification.AuthenticationTicket.Identity.AuthenticationType, CustomClaimNames.EpiUsername, JwtClaimTypes.Role);

                        // split claims to two sets: role claims and other claims
                        List <Claim> roleClaims  = new List <Claim>();
                        List <Claim> otherClaims = new List <Claim>();

                        foreach (var c in userInfoResponse.Claims)
                        {
                            if (string.Compare(c.Type, CustomClaimNames.Permission, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                roleClaims.Add(c);
                            }
                            else
                            {
                                otherClaims.Add(c);
                            }
                        }

                        // get the preferred username claim and if it doesn't exist use sub claim value
                        string username = otherClaims.GetClaimValue(JwtClaimTypes.PreferredUserName) ?? notification.JwtSecurityToken.Subject;
                        authClaimsIdentity.AddClaim(new Claim(CustomClaimNames.EpiUsername, username));

                        // should we add the claim to allow publishing of content
                        bool addPublisherClaim = false;

                        // is the user admin
                        var adminUserClaim = roleClaims.Find(c => string.Compare(c.Value, PermissionGroupNames.WebSiteSuperUser, StringComparison.OrdinalIgnoreCase) == 0);

                        if (adminUserClaim != null)
                        {
                            //   authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, EpiRoles.Admin));
                            addPublisherClaim = true;
                        }

                        // you could have a claim for users from previous CMS and then you could have a custom mapping from that claim to new claim(s) used by Episerver
                        //var oldEditorClaim = roleClaims.Find(c => string.Compare(c.Value, "BOGUS_OLD_CMS_USER", StringComparison.OrdinalIgnoreCase) == 0);
                        //if (oldEditorClaim != null)
                        //{
                        //    authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, "WebEditors"));
                        //    addPublisherClaim = true;
                        //}

                        // is the user editor
                        var editUserClaim = roleClaims.Find(c => string.Compare(c.Value, PermissionGroupNames.WebSiteEditor, StringComparison.OrdinalIgnoreCase) == 0);

                        if (editUserClaim != null)
                        {
                            //  authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, EpiRoles.Editor));
                            addPublisherClaim = true;
                        }

                        // is the user a reader without edit/publishing rights
                        var readerUserClaim = roleClaims.Find(c => string.Compare(c.Value, PermissionGroupNames.WebSiteReader, StringComparison.OrdinalIgnoreCase) == 0);

                        if (readerUserClaim != null)
                        {
                            // authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, EpiRoles.Editor));
                            // user will get the WebEditors role but not the role to publish/edit
                            // WebEditors role should only be used to grant access to the edit mode BUT not give any rights for content
                            // that is why we have the "SitePublishers" in this demo, we'll grant full permissions for content for this group
                            // but in real life scenario, you would have different and maybe more granular roles for different actions
                        }

                        // should we grant the publishing rights to the user
                        if (addPublisherClaim)
                        {
                            //   authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, EpiRoles.Publisher));
                        }

                        // next get the email, givenname and surname claim values, our IdP uses JwtClaimTypes
                        // so this is not something that you can copy to your solution, but you need to check what claims your IdP returns
                        authClaimsIdentity.AddClaimFromSource(ClaimTypes.Email, otherClaims, JwtClaimTypes.Email);
                        authClaimsIdentity.AddClaimFromSource(ClaimTypes.GivenName, otherClaims, JwtClaimTypes.GivenName);
                        authClaimsIdentity.AddClaimFromSource(ClaimTypes.Surname, otherClaims, JwtClaimTypes.FamilyName);

                        // For now we don't need the access token, besides it expires in 60 minutes and we can't refresh it as we don't request for a refreshtoken
                        //authClaimsIdentity.AddClaim(new Claim(OpenIdConnectParameterNames.AccessToken, tokenResponse.AccessToken));
                        //authClaimsIdentity.AddClaim(new Claim("expires_at", DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToString()));

                        // this is needed for the logout, logout uses id_token_hint
                        authClaimsIdentity.AddClaim(new Claim(OpenIdConnectParameterNames.IdToken, notification.ProtocolMessage.IdToken));

                        // replace the automatically created authenticationticket with our ticket which contains our minimal set of claims
                        // remember to pass in the original ticket properties for the new ticket
                        notification.AuthenticationTicket = new AuthenticationTicket(authClaimsIdentity, notification.AuthenticationTicket.Properties);
                        System.Diagnostics.Debug.WriteLine($"Authenticated and logging in user '{GetFullName(notification.JwtSecurityToken.Claims)}' (sub: {notification.JwtSecurityToken.Subject}).");

                        Logger.Information($"Authenticated and logging in user '{GetFullName(authClaimsIdentity.Claims)}' (sub: {notification.JwtSecurityToken.Subject}).");

                        // Sync user and the roles to EPiServer in the background
                        // See: https://world.episerver.com/documentation/developer-guides/CMS/security/integrate-azure-ad-using-openid-connect/
                        // Please note that until a user with a role has logged in, you can't apply permissions to that role (as Episerver doesn't naturally know about that role)
                        await ServiceLocator.Current.GetInstance <ISynchronizingUserService>().SynchronizeAsync(notification.AuthenticationTicket.Identity);
                    },
                    AuthenticationFailed = notification =>
                    {
                        Logger.Error($"Authentication failed: {notification.Exception.Message}");

                        notification.HandleResponse();

                        // TODO: redirect to a nice error page
                        // does 302 redirect, but SEO is not your concern here
                        // notification.Response.Redirect("/your/nice/error/page/address/here/");
                        notification.Response.Write(notification.Exception.Message);
                        return(Task.FromResult(0));
                    },
                    SecurityTokenReceived = notification =>
                    {
                        // purely to log "stages" for demo and debugging, in real app usually you can leave this notification un-implemented

                        if (Logger.IsDebugEnabled())
                        {
                            try
                            {
                                Logger.Debug($"Security token received. Code: '{notification.ProtocolMessage.Code}', IdToken: '{notification.ProtocolMessage.IdToken}'.");
                            }
                            catch (Exception ex)
                            {
                                Logger.Error($"Security token received. Failed to read Code and IdToken for debug logging.", ex);
                            }
                        }

                        return(Task.FromResult(0));
                    },
                    SecurityTokenValidated = notification =>
                    {
                        // purely to log "stages" for demo and debugging, in real app usually you can leave this notification un-implemented

                        if (Logger.IsDebugEnabled())
                        {
                            try
                            {
                                Logger.Debug($"Security token validated for sub: {notification.AuthenticationTicket.Identity.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject)?.Value}.");
                            }
                            catch (Exception ex)
                            {
                                Logger.Error($"Security token validated. Failed to read values from protocol message for debug logging.", ex);
                            }
                        }

                        return(Task.FromResult(0));
                    },
                    MessageReceived = notification =>
                    {
                        // purely to log "stages" for demo and debugging, in real app usually you can leave this notification un-implemented

                        if (Logger.IsDebugEnabled())
                        {
                            Logger.Debug($"Message received.");
                        }

                        return(Task.FromResult(0));
                    }
                }
            });

            // see: https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline#stage-markers
            app.UseStageMarker(PipelineStage.Authenticate);

            // TODO: your util url path here
            app.Map("/util/login.aspx", map =>
            {
                map.Run(ctx =>
                {
                    if (ctx.Authentication.User == null || !ctx.Authentication.User.Identity.IsAuthenticated)
                    {
                        // trigger authentication
                        ctx.Response.StatusCode = 401;
                    }
                    else
                    {
                        ctx.Response.Redirect("/");
                    }

                    return(Task.FromResult(0));
                });
            });

            // TODO: your util url path here
            app.Map("/util/logout.aspx", map =>
            {
                map.Run(ctx =>
                {
                    ctx.Authentication.SignOut();
                    return(Task.FromResult(0));
                });
            });
        }
예제 #7
0
        public void Configuration(IAppBuilder app)
        {
            // The UniqueClaimTypeIdentifier setting requires that all claims-based identities must return a unique value for that claim type.
            // This adjusts the anti-CSRF protection to use the sub claim and is necessary as a result of setting our inbound claim type map like we have.
            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";

            // By setting this to a new dictionary of string and string we are essentially clearing the mapper, allowing the JWT middleware to use the claim types
            // that are sent by Identity Server, instead of it mapping them to the Microsoft XML schema types(for example we'll get name instead of
            // http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name).
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.UseCookieAuthentication(new CookieAuthenticationOptions {
                AuthenticationType = "Cookies"
            });

            // The Katana middleware is in charge of detecting when the user needs to be redirected to the OpenID Connect Provider and handling the subsequent interactions.
            // This middleware will then log us in to our application as a result.
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId  = "hybridclient",
                Authority = IdServBaseUri,
                //RedirectUri = ClientUri,
                //PostLogoutRedirectUri = ClientUri,
                ResponseType = "code id_token token",
                Scope        = "openid profile email roles offline_access",
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },
                SignInAsAuthenticationType = "Cookies",
                Notifications =
                    new OpenIdConnectAuthenticationNotifications
                {
                    // Use the Authorisation Code Flow - it's more secure than Implicit flow and allows us to request refresh tokens
                    AuthorizationCodeReceived = async n =>
                    {
                        // Check the uri and get the tenant
                        var uri    = $"{n.Request.Scheme}://{n.Request.Host}/";
                        var tenant = string.Empty;

                        if (this.ValidateUri(uri))
                        {
                            tenant = this.Between(uri, "//", ".");
                        }
                        else
                        {
                            // TODO: Some kind of error here?
                        }

                        // Here we are using the UserInfoClient helper from the IdentityModel library to retrieve the user's claims and then
                        // creating a new ClaimsIdentity, keeping the AuthenticationType the same. We are then populating this identity with
                        // any claims we want both from the existing ClaimsIdentity and then any claims we received from the userinfo endpoint.
                        // We can then store these claims in our authentication cookie.
                        var userInfoClient   = new UserInfoClient(new Uri(UserInfoEndpoint), n.ProtocolMessage.AccessToken);
                        var userInfoResponse = await userInfoClient.GetAsync();

                        var identity = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        identity.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);

                        // To add support for long lived logins, we'll need get a refresh token from our authorization server.
                        // This refresh token can then be used to obtain fresh access tokens when the current one becomes invalid or expires.
                        // Here we are using another helper class from the IdentityModel library, this time TokenClient.
                        // This is used for simple handling of OAuth requests and is internally a wrapper around HttpClient.
                        // By trading in our Authorization Code like this we receive a new access token and a refresh token along with it.
                        var tokenClient = new TokenClient(TokenEndpoint, "hybridclient", "idsrv3test");
                        var response    = await tokenClient.RequestAuthorizationCodeAsync(n.Code, uri);

                        identity.AddClaim(new Claim("access_token", response.AccessToken));
                        identity.AddClaim(
                            new Claim("expires_at", DateTime.UtcNow.AddSeconds(response.ExpiresIn).ToLocalTime().ToString(CultureInfo.InvariantCulture)));

                        // We can only get the refresh token because we request the offline access scope in the client
                        identity.AddClaim(new Claim("refresh_token", response.RefreshToken));

                        // To use the post logout redirect(also logs us out of Identity Server) we should also supply the previously issued ID token in order to give the
                        // OpenID Connect Provider some sort of idea about the current authenticated session.
                        identity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                        // This ticket is used to set up our claims principal
                        n.AuthenticationTicket = new AuthenticationTicket(
                            identity,
                            n.AuthenticationTicket.Properties);
                    },
                    RedirectToIdentityProvider = n =>
                    {
                        var uri = $"{n.Request.Scheme}://{n.Request.Host}/";

                        if (this.ValidateUri(uri))
                        {
                            n.ProtocolMessage.RedirectUri           = uri;
                            n.ProtocolMessage.PostLogoutRedirectUri = uri;
                        }
                        else
                        {
                            // TODO: Some kind of error here?
                        }

                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.AuthenticationRequest)
                        {
                            var tenant = this.Between(uri, "//", ".");
                            n.ProtocolMessage.AcrValues = $"tenant:{tenant}";
                        }

                        // This allows us to redirect back to our site on logout of IdentityServer (but not automatically)
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
                            n.ProtocolMessage.IdTokenHint = idTokenHint;
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #8
0
        public void Configuration(IAppBuilder app)
        {
            var IDSSettings = IdentitySettingsConfig.IDSSettings;

            if (!string.IsNullOrEmpty(IdentitySettingsConfig.Msg))
            {
                app.Run(async context =>
                {
                    context.Response.ContentType = "text/plain";
                    await context.Response.WriteAsync(IdentitySettingsConfig.Msg);
                });
            }
            else
            {
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = IDSSettings.Cookies_AuthenticationType,
                    LoginPath          = new PathString(IDSSettings.Cookies_LoginPath),
                    CookieName         = IDSSettings.Cookies_CookieName,
                    CookieDomain       = IDSSettings.Cookies_CookieDomain
                });

                app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
                {
                    AuthenticationType         = IDSSettings.AuthenticationType,
                    SignInAsAuthenticationType = IDSSettings.SignInAsAuthenticationType,
                    Authority             = IDSSettings.Authority,
                    RedirectUri           = IDSSettings.RedirectUri,
                    ClientId              = IDSSettings.ClientId,
                    ClientSecret          = IDSSettings.ClientSecret,
                    Scope                 = IDSSettings.Scope,
                    ResponseType          = IDSSettings.ResponseType,
                    PostLogoutRedirectUri = IDSSettings.RedirectUri,
                    Notifications         = new OpenIdConnectAuthenticationNotifications
                    {
                        SecurityTokenValidated = async n =>
                        {
                            var claims_to_exclude = new[] { "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash" };

                            //Exclude unnecessary claims
                            var claims_to_keep =
                                n.AuthenticationTicket.Identity.Claims
                                .Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();

                            //Add id_token to user claims
                            claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));

                            //Search userinfo from IS Claims
                            if (n.ProtocolMessage.AccessToken != null)
                            {
                                claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));
                                var userInfoClient   = new UserInfoClient(new System.Uri(IDSSettings.EndpointUserInfo), n.ProtocolMessage.AccessToken);
                                var userInfoResponse = await userInfoClient.GetAsync();
                                var userInfoClaims   = userInfoResponse.Claims
                                                       .Select(x => new Claim(x.Item1, x.Item2));
                                claims_to_keep.AddRange(userInfoClaims);
                            }

                            var ci = new ClaimsIdentity(
                                n.AuthenticationTicket.Identity.AuthenticationType,
                                "name", "role");
                            ci.AddClaims(claims_to_keep);

                            n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(
                                ci, n.AuthenticationTicket.Properties
                                );
                        },
                        RedirectToIdentityProvider = n =>
                        {
                            if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                            {
                                var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
                                n.ProtocolMessage.IdTokenHint = id_token;
                            }

                            return(Task.FromResult(0));
                        },
                        AuthenticationFailed = context =>
                        {
                            if (context.Exception is OpenIdConnectProtocolInvalidNonceException)
                            {
                                // Handle Microsoft.IdentityModel.Protocols.OpenIdConnectProtocolInvalidNonceException:
                                // IDX10311: RequireNonce is 'true' (default) but validationContext.Nonce is null. A nonce
                                // cannot be validated. If you don't need to check the nonce, set
                                // OpenIdConnectProtocolValidator.RequireNonce to 'false'.
                                if (context.Exception.Message.Contains("IDX10311"))
                                {
                                    context.SkipToNextMiddleware();
                                }
                            }
                            return(Task.FromResult(0));
                        }
                    }
                });
            }
        }
        public void Configuration(IAppBuilder app)
        {
            app.Use(async(Context, next) =>
            {
                // request processing - do something here
                await next.Invoke();
                // response processing - do something here
            });
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            //app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseCookieAuthentication(new CookieAuthenticationOptions {
                CookieName = "Okta_OIDCSApp"
            });

            //string storeRedirectUrl = null;

            //var protocolValidator = new OpenIdConnectProtocolValidator();
            //protocolValidator.RequireNonce = true;
            //protocolValidator.RequireStateValidation = false;
            //protocolValidator.RequireState = false;


            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId     = clientId,
                ClientSecret = clientSecret,
                Authority    = authority,
                //Note: this can be done dynamically below
                RedirectUri           = redirectUri,
                ResponseType          = responseType,
                Scope                 = scope,
                PostLogoutRedirectUri = postLogoutRedirectUri,
                //ProtocolValidator = protocolValidator,


                //Required to validate the signature
                TokenValidationParameters = new TokenValidationParameters
                {
                    ValidAudience            = WebConfigurationManager.AppSettings["oidc.spintweb.clientId"],
                    ValidIssuer              = WebConfigurationManager.AppSettings["oidc.issuer"],
                    ValidateIssuerSigningKey = true,
                    ValidateAudience         = true,
                    ValidateIssuer           = true,
                    ValidateLifetime         = true
                                               //ValidateTokenReplay = false
                },

                //Must be placed after 'TokenValidationParameters'
                // SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,



                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    MessageReceived = n =>
                    {
                        logger.Debug("MessageReceived");
                        string myCustomParameter;
                        var protectedState = n.ProtocolMessage.State.Split('=')[1];
                        var state          = n.Options.StateDataFormat.Unprotect(protectedState);
                        state.Dictionary.TryGetValue("MyCustomParameter", out myCustomParameter);


                        return(Task.FromResult(0));
                    },

                    AuthorizationCodeReceived = async n =>
                    {
                        //when response type of code is specific in responseType
                        logger.Debug("AuthorizationCodeReceived");
                        string code = n.Code;

                        var tokenClient   = new TokenClient(authority + "/oauth2/v1/token", clientId, clientSecret);
                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, redirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        //method 1 for storing token
                        HttpContext.Current.Session["access_token"]  = tokenResponse.AccessToken;
                        HttpContext.Current.Session["refresh_token"] = tokenResponse.RefreshToken;
                        //HttpContext.Current.Session["id_token_ac"] = tokenResponse.IdentityToken;

                        //method 2 for storing token;
                        var claims = new List <Claim>();
                        claims.Add(new Claim("id_token_ac", tokenResponse.IdentityToken));
                        claims.Add(new Claim("access_token", tokenResponse.AccessToken));
                        claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
                        //should NOT add claims since the token has not been validated at this notification level
                        n.AuthenticationTicket.Identity.AddClaims(claims);


                        var userInfoClient   = new UserInfoClient(authority + "/oauth2/v1/userinfo");
                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        //add claims from userInfo endpoint
                        claims.AddRange(userInfoResponse.Claims);



                        //return Task.FromResult(0);
                    },
                    AuthenticationFailed = n =>
                    {
                        logger.Debug("AuthenticationFailed");
                        n.HandleResponse();
                        logger.Debug(n.Exception.Message);


                        if (n.Exception.Message == "access_denied")
                        {
                            //context.Response.Redirect(WebConfigurationManager.AppSettings["oidc.authError"]);
                            n.Response.Redirect("/Home/AuthError?message=" + n.Exception.Message);
                        }
                        if (n.Exception.Message == "login_required")
                        {
                            //context.Response.Redirect(WebConfigurationManager.AppSettings["oidc.authError"]);
                            n.Response.Redirect("/Home/AuthError?message=" + n.Exception.Message);
                        }
                        else
                        {
                            //context.Response.Redirect(WebConfigurationManager.AppSettings["oidc.authError"]);
                            n.Response.Redirect("/Home/AuthError?message=" + n.Exception.Message);
                        }

                        //if (context.Exception.Message.StartsWith("IDX21323"))
                        //{
                        //    context.SkipToNextMiddleware();
                        //    return Task.FromResult(0);

                        //    context.Response.Redirect(storeRedirectUrl);
                        //}

                        return(Task.FromResult(0));
                    },
                    SecurityTokenReceived = n =>
                    {
                        logger.Debug("SecurityTokenReceived");


                        return(Task.FromResult(0));
                    },
                    SecurityTokenValidated = n =>
                    {
                        logger.Debug("SecurityTokenValidated");
                        string nameIdent = n.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                        string friendlyname = n.AuthenticationTicket.Identity.FindFirst("friendlyname").Value;
                        n.AuthenticationTicket.Identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", friendlyname));

                        //add id_token to calims to support OIDC logout
                        var id_token = n.ProtocolMessage.IdToken;
                        n.AuthenticationTicket.Identity.AddClaim(new Claim("id_token", id_token));
                        // Add roles based on Okta groups
                        foreach (var group in n.AuthenticationTicket.Identity.Claims.Where(x => x.Type == "groups"))
                        {
                            n.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Role, group.Value));
                        }

                        string scheme    = n.Request.Scheme;
                        string authority = n.Request.Uri.Authority;
                        n.AuthenticationTicket.Properties.RedirectUri = scheme + "://" + authority + "/Home/PostLogin";

                        return(Task.FromResult(0));
                    },
                    //added to support idp parameter on authorize endpoint
                    RedirectToIdentityProvider = n =>
                    {
                        logger.Debug("RedirectToIdentityProvider");

                        if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Authentication)
                        {
                            //use this if only allowed access from entry application
                            //n.ProtocolMessage.SetParameter("prompt", "none"); //does not allow a login UI if no session
                            //use this to supercede an ACTIVE user
                            //n.ProtocolMessage.SetParameter("prompt", "login"); //forces login even if there is a ACTIVE Okta session
                            //use this to force consent,even if previously granted
                            //n.ProtocolMessage.SetParameter("prompt", "consent");

                            //Gobal Login Integration or Inbound IDP
                            //set value in web.config
                            //n.ProtocolMessage.SetParameter("idp", idp);



                            ////create redirect_url parameter dynamically
                            ////all variants MUST be included in Okta integration
                            //string absoluteUri = context.Request.Uri.AbsoluteUri;
                            //string myRedirectUrl = (absoluteUri.Substring(0, absoluteUri.IndexOf(context.Request.Uri.LocalPath))) + "/signin-oidc";
                            //string httpRule = context.Request.Headers["Front-End-Https"];
                            //if (!string.IsNullOrEmpty(httpRule) && httpRule == "On")
                            //{
                            //    int index = myRedirectUrl.IndexOf("http://");
                            //    if (myRedirectUrl.IndexOf("http://") != -1)
                            //    {
                            //        myRedirectUrl = myRedirectUrl.Replace("http://", "https://");
                            //    }
                            //}
                            //context.ProtocolMessage.RedirectUri = myRedirectUrl.ToLower();

                            //add state parameter to OIDC
                            var stateQueryString = n.ProtocolMessage.State.Split('=');
                            var protectedState   = stateQueryString[1];
                            var state            = n.Options.StateDataFormat.Unprotect(protectedState);
                            state.Dictionary.Add("MyCustomParameter", "myClientAppStateInfo");
                            n.ProtocolMessage.State = stateQueryString[0] + "=" + n.Options.StateDataFormat.Protect(state);
                        }

                        if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Logout)
                        {
                            var idToken = n.OwinContext.Authentication.User.Claims
                                          .FirstOrDefault(c => c.Type == "id_token")?.Value;
                            n.ProtocolMessage.IdTokenHint = idToken;
                        }
                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #10
0
        private async Task <IEnumerable <Claim> > GetUserInfoClaimsAsync(string accessToken)
        {
            IEnumerable <Claim> userData = new List <Claim>();
            //Get UserInfo data when correct scope is set
            var userInfoClient = new UserInfoClient(AppController.userinfoEndpoint);

            UserInfoResponse userInfoResponse = await userInfoClient.GetAsync(accessToken);

            if (userInfoResponse.HttpStatusCode == HttpStatusCode.OK)
            {
                //Read UserInfo Details
                userData = userInfoResponse.Json.ToClaims();

                foreach (Claim item in userData)
                {
                    if (item.Type == "sub" && item.Value != null)
                    {
                        sub = item.Value;
                    }
                    if (item.Type == "email" && item.Value != null)
                    {
                        email = item.Value;
                    }
                    if (item.Type == "emailVerified" && item.Value != null)
                    {
                        emailVerified = item.Value;
                    }
                    if (item.Type == "givenName" && item.Value != null)
                    {
                        givenName = item.Value;
                    }
                    if (item.Type == "familyName" && item.Value != null)
                    {
                        familyName = item.Value;
                    }
                    if (item.Type == "phoneNumber" && item.Value != null)
                    {
                        phoneNumber = item.Value;
                    }
                    if (item.Type == "phoneNumberVerified" && item.Value != null)
                    {
                        phoneNumberVerified = item.Value;
                    }

                    if (item.Type == "address" && item.Value != null)
                    {
                        Address jsonObject = JsonConvert.DeserializeObject <Address>(item.Value);

                        if (jsonObject.StreetAddress != null)
                        {
                            streetAddress = jsonObject.StreetAddress;
                        }
                        if (jsonObject.Locality != null)
                        {
                            locality = jsonObject.Locality;
                        }
                        if (jsonObject.Region != null)
                        {
                            region = jsonObject.Region;
                        }
                        if (jsonObject.PostalCode != null)
                        {
                            postalCode = jsonObject.PostalCode;
                        }
                        if (jsonObject.Country != null)
                        {
                            country = jsonObject.Country;
                        }
                    }
                }
            }

            return(userData);
        }
    public void Configuration(IAppBuilder app)
    {
        AntiForgeryConfig.UniqueClaimTypeIdentifier = Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Subject;
        JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });
        var openIdConfig = new OpenIdConnectAuthenticationOptions
        {
            Authority    = "https://localhost:44301/identity",
            ClientId     = "baseballStats",
            Scope        = "openid profile roles baseballStatsApi",
            RedirectUri  = "https://localhost:44300/",
            ResponseType = "id_token token",
            SignInAsAuthenticationType = "Cookies",
            UseTokenLifetime           = false,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = async n =>
                {
                    var userInfoClient = new UserInfoClient(
                        new Uri(n.Options.Authority + "/connect/userinfo"),
                        n.ProtocolMessage.AccessToken);
                    var userInfo = await userInfoClient.GetAsync();

                    // create new identity and set name and role claim type
                    var nid = new ClaimsIdentity(
                        n.AuthenticationTicket.Identity.AuthenticationType,
                        Thinktecture.IdentityServer.Core.Constants.ClaimTypes.GivenName,
                        Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Role);
                    userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2)));
                    // keep the id_token for logout
                    nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                    // add access token for sample API
                    nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
                    // keep track of access token expiration
                    nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));
                    // add some other app specific claim
                    nid.AddClaim(new Claim("app_specific", "some data"));
                    n.AuthenticationTicket = new AuthenticationTicket(
                        nid,
                        n.AuthenticationTicket.Properties);
                    n.Request.Headers.SetValues("Authorization ", new string[] { "Bearer ", n.ProtocolMessage.AccessToken });
                }
            }
        };

        app.UseOpenIdConnectAuthentication(openIdConfig);
        app.UseResourceAuthorization(new AuthorizationManager());
        app.Map("/api", inner =>
        {
            var bearerTokenOptions = new IdentityServerBearerTokenAuthenticationOptions
            {
                Authority      = "https://localhost:44301/identity",
                RequiredScopes = new[] { "baseballStatsApi" }
            };
            inner.UseIdentityServerBearerTokenAuthentication(bearerTokenOptions);
            var config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();
            inner.UseWebApi(config);
        });
    }
예제 #12
0
        /// <summary>
        /// Произвести попытку подключить клиента к identity server с текущей временной конфигурацией.
        /// Ничего не делает, если конфигурация ещё не заполнена, то есть
        /// <see cref="AuthServerConfiguration.IsComplete"/> возвращает false.
        /// </summary>
        /// <param name="app">Сборщик приложения.</param>
        /// <param name="config">Временная конфиграция клиента для данного сборщика приложения.</param>
        /// <returns><paramref name="app"/>.</returns>
        private static IAppBuilder TryConfigureAuthServer(IAppBuilder app, AuthServerConfiguration config)
        {
            if (!config.IsComplete)
            {
                return(app);
            }

            // Это нужно для защиты от CSRF-атак
            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";

            // А это нужно, чтобы ключи Claims-ов пользователя имели адекыватные названия
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app
            .UseCookieAuthentication(new CookieAuthenticationOptions
            {
                // Используем cookie аутентификацию
                AuthenticationType = "Cookies",
                ExpireTimeSpan     = TimeSpan.FromMinutes(14),
            })
            .UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                // Задаём адрес identity server
                Authority = config.IdSrvAddress,

                // идентификатор данного клиента, можно найти в IS.Clients
                ClientId = config.ClientId,

                // Секрет приложения-клиента
                ClientSecret = config.ClientSecret,

                // адрес, на который перенаправляем после аутентификации, совпадает с соответствующим в IS.Clients
                RedirectUri = config.OwnAddress,

                // токен, который запрашиваем, связано со значением Flows.Hybrid в IS.Clients
                ResponseType = "code id_token token",

                // адрес, на который редиректит после выхода, совпадает с соответствующим в IS.Clients
                PostLogoutRedirectUri      = config.OwnAddress,
                SignInAsAuthenticationType = "Cookies",
                UseTokenLifetime           = false,

                // Фактически обработчики различных событий
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the access token to retrieve claims from userinfo
                        var uriToUserInfo    = new Uri(config.IdSrvAddress + "/connect/userinfo");
                        var userInfoClient   = new UserInfoClient(uriToUserInfo, n.ProtocolMessage.AccessToken);
                        var userInfoResponse = await userInfoClient.GetAsync();

                        string userName = userInfoResponse?.Claims?.FirstOrDefault(c => c.Item1 == "name")?.Item2;

                        if (userName == null)
                        {
                            // n.OwinContext.Authentication.SignOut();
                            return;
                        }

                        // Создаём claims-ы пользователя, которые в дальнейшем будут видны в методах контроллера
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(n.AuthenticationTicket.Identity.Claims);

                        // имя пользователя (логин)
                        id.AddClaim(new Claim("name", userName));

                        // и id_token (нужен для logout-а)
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
                        n.AuthenticationTicket = new AuthenticationTicket(id, n.AuthenticationTicket.Properties);
                    },

                    // Нам надо обработать событие выхода пользователя
                    RedirectToIdentityProvider = n =>
                    {
                        // Это взято из примера: https://identityserver.github.io/Documentation/docsv2/overview/mvcGettingStarted.html
                        if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)
                        {
                            // Вот тут нам нужен id_token, который мы добавляли в claims-ы пользователя чуть выше
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    },

                    // Исправляет баг, см. https://github.com/IdentityServer/IdentityServer3/issues/542
                    AuthenticationFailed = n =>
                    {
                        if (n.Exception.Message.Contains("IDX21323"))
                        {
                            n.SkipToNextMiddleware();
                        }

                        return(Task.FromResult(0));
                    },
                },
            });

            if (config.UseWebForms)
            {
                app.UseStageMarker(PipelineStage.Authenticate);
            }

            /* Api может пригодиться в будущем, на всякий случай оставил, чтобы не затерялось в истории комитов
             *
             * app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
             * {
             *  Authority = "https://localhost:44363/identity",
             *  RequiredScopes = new[] { "api1" },
             *  DelayLoadMetadata = true,
             *
             *  ClientId = "api1",
             *  ClientSecret = "secret"
             * });*/

            return(app);
        }
        public void ConfigureAuth(IAppBuilder app)
        {
            string oktaOAuthClientId = ConfigurationManager.AppSettings["okta:OauthClientId"] as string;
            string oidcClientSecret  = ConfigurationManager.AppSettings["okta:OAuthClientSecret"];
            string oidcAuthority     = ConfigurationManager.AppSettings["okta:OAuthAuthority"] as string;
            string oidcRedirectUri   = ConfigurationManager.AppSettings["okta:OAuthRedirectUri"] as string;
            string oidcResponseType  = ConfigurationManager.AppSettings["okta:OAuthResponseType"] as string;
            string oauthScopes       = ConfigurationManager.AppSettings["okta:OAuthScopes"];

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId     = oktaOAuthClientId,
                Authority    = oidcAuthority,
                RedirectUri  = oidcRedirectUri,
                ResponseType = oidcResponseType,
                Scope        = oauthScopes,

                SignInAsAuthenticationType = "Cookies",
                UseTokenLifetime           = true,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            oidcAuthority + Constants.TokenEndpoint,
                            oktaOAuthClientId,
                            oidcClientSecret, AuthenticationStyle.BasicAuthentication);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(new Uri(oidcAuthority + Constants.UserInfoEndpoint), tokenResponse.AccessToken);

                        var userInfoResponse = await userInfoClient.GetAsync();

                        //// create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        //adding the claims we get from the userinfo endpoint
                        var idClaims = userInfoResponse.GetClaimsIdentity();
                        id.AddClaims(idClaims.Claims);

                        //also adding the ID, Access and Refresh tokens to the user claims
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        if (tokenResponse.RefreshToken != null)
                        {
                            id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        }

                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        if (tokenResponse.RefreshToken != null)
                        {
                            id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        }

                        // Make sure the Name claim is populated (for Identity.Name)
                        var nameClaim = new Claim(ClaimTypes.Name, idClaims.Claims.FirstOrDefault(c => c.Type == "name")?.Value);
                        id.AddClaim(nameClaim);

                        n.AuthenticationTicket = new AuthenticationTicket(new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType),
                                                                          n.AuthenticationTicket.Properties);
                    },
                }
            });
        }
예제 #14
0
        //private const short ExpireTimeSpan = 1;
        //private const string AuthenticationCookieName = "Mpix.Com.AuthCookie";
        public static void ConfigureAuth(IAppBuilder app)
        {
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            var jwtHandler = new JwtSecurityTokenHandler();

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                SlidingExpiration  = true,
                CookieName         = "UserClientAuth",
                Provider           = new CookieAuthenticationProvider
                {
                    OnResponseSignedIn = async context =>
                    {
                        //var idToken = context.Identity.Claims.FirstOrDefault(c => c.Type == "id_token").Value;
                        //if (jwtHandler.CanReadToken(idToken))
                        //{
                        //    var token = jwtHandler.ReadJwtToken(idToken);
                        //    var guid = token.Claims.FirstOrDefault(c => c.Type == "sub").Value;

                        //    //aContext.SetUserID(Guid.Parse(guid), false);
                        //}
                        var guid = context.Identity.Claims.FirstOrDefault(c => c.Type == "sub").Value;
                    },
                    OnValidateIdentity = async context =>
                    {
                    }
                }
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = PublicClientId,
                ClientSecret          = Secret,
                Authority             = IdentityServerUrl,
                RedirectUri           = ClientUrl + "/signin-oidc",
                PostLogoutRedirectUri = ClientUrl + "/signout-callback-oidc",
                ResponseType          = "id_token",
                RequireHttpsMetadata  = false,
                UseTokenLifetime      = false,
                Scope = "openid profile",

                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },

                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                AuthenticationType         = "oidc",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async(notification) =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(IdentityServerUrl_TokenEndpoint, PublicClientId, Secret);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(notification.Code, notification.RedirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(IdentityServerUrl_UserInfoEndpoint);

                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        // create new identity
                        var claimsIdentity = new ClaimsIdentity(notification.AuthenticationTicket.Identity.AuthenticationType, "name", "role");
                        claimsIdentity.AddClaims(userInfoResponse.Claims
                                                 .Where(x => x.Type != "sub") // filter sub since we're already getting it from id_token
                                                 .Select(x => new Claim(x.Type, x.Value)));

                        claimsIdentity.AddClaim(new Claim("id_token", notification.ProtocolMessage.IdToken));
                        claimsIdentity.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        claimsIdentity.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        claimsIdentity.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        claimsIdentity.AddClaim(new Claim("sid", notification.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        notification.AuthenticationTicket = new AuthenticationTicket(claimsIdentity, notification.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = (notification) =>
                    {
                        // if signing out, add the id_token_hint
                        if (notification.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Logout)
                        {
                            var idTokenHint = notification.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
                            notification.ProtocolMessage.IdTokenHint = idTokenHint;
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
            app.UseStageMarker(PipelineStage.Authenticate);
        }
예제 #15
0
        public void Configuration(IAppBuilder app)
        {
            // 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
            // Configure the sign in cookie
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies",
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority = "http://localhost:5000/",
                ClientId  = "crm",
                //Scope = "openid profile roles",
                Scope       = "openid profile roles customersapi portfolioapi",
                RedirectUri = "http://localhost:7000/",
                //ResponseType = "id_token",
                ResponseType = "id_token token",        //call the api on behalf of the user. Get the id token & access token together
                SignInAsAuthenticationType = "Cookies",
                UseTokenLifetime           = false,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = n =>
                    {
                        var id = n.AuthenticationTicket.Identity;

                        // we want to keep first name, last name, subject and roles, comment when access token is requested
                        //var givenName = id.FindFirst("given_name");
                        //var familyName = id.FindFirst("family_name");
                        //var sub = id.FindFirst("sub");
                        //var roles = id.FindAll("role");

                        // create new identity and set name and role claim type
                        var nid = new ClaimsIdentity(
                            id.AuthenticationType,
                            "given_name",
                            "role");

                        // comment when access token is requested
                        //nid.AddClaim(givenName);
                        //nid.AddClaim(familyName);
                        //nid.AddClaim(sub);
                        //nid.AddClaims(roles);

                        // get userinfo data. Add when access token is requested
                        var userInfoClient = new UserInfoClient(n.Options.Authority + "/connect/userinfo");

                        var userInfo = userInfoClient.GetAsync(n.ProtocolMessage.AccessToken);
                        userInfo.Result.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Type, ui.Value)));


                        // add some other app specific claim
                        nid.AddClaim(new Claim("app_specific", "some data"));

                        // add id token
                        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                        // add access token for sample API. Add when access token is requested
                        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                        // keep track of access token expiration. Add when access token is requested
                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            nid,
                            n.AuthenticationTicket.Properties);

                        return(Task.FromResult(0));
                    },
                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });

            //AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();
        }
예제 #16
0
        public void Configuration(IAppBuilder app)
        {
            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();


            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority                  = Constants.IdentityServerUri,
                ClientId                   = Constants.ImplicitClient,
                Scope                      = "openid profile roles apiAccess",
                RedirectUri                = Constants.ImplicitClientUri,
                ResponseType               = "id_token token",
                UseTokenLifetime           = false,
                SignInAsAuthenticationType = "Cookies",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var nid = new ClaimsIdentity(
                            n.AuthenticationTicket.Identity.AuthenticationType,
                            "givenname",
                            "role");

                        // get userinfo data
                        var userInfoClient = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken);

                        var userInfo = await userInfoClient.GetAsync();

                        if (userInfo.Claims != null)
                        {
                            userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Item1, ui.Item2)));
                        }


                        // keep the id_token for logout
                        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                        // add access token for sample API
                        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                        // keep track of access token expiration
                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.PostLogoutRedirectUri = Constants.ImplicitClientUri;
                                n.ProtocolMessage.IdTokenHint           = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });

            app.UseResourceAuthorization(new AuthorizationManager());
        }
        public async Task <UserInfoResponse> GetUserInfo(string token)
        {
            var client = new UserInfoClient(_googleOptions.UserInfoEndpoint);

            return(await client.GetAsync(token));
        }
예제 #18
0
        public void Configuration(IAppBuilder app)
        {
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;

            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";

            // set the default authentication type to 'Cookies'
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                ExpireTimeSpan    = TimeSpan.FromMinutes(OIDCInMemoryConfiguration.AuthCookieValidMinutes),
                SlidingExpiration = true
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = "ZZLouDKZUq6NrBjzyLvznrZf1AfCjJvg",
                ClientSecret          = "3K4VDmK24SVLqI74ZOgK2RYSDIb2y-kePiIW0pwIyKA9baB96tA_k66i2taB-7XH",
                Authority             = "https://tietoevry-partner-sandbox.eu.auth0.com/",
                RedirectUri           = "https://localhost:44392/signin-oidc",
                PostLogoutRedirectUri = "https://localhost:44392/signout-oidc",
                Scope                     = $"openid email profile",
                ResponseType              = "code id_token",
                RequireHttpsMetadata      = true,
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType       = "sub",
                    RoleClaimType       = "role",
                    ValidateTokenReplay = true
                },
                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                UseTokenLifetime           = false,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    RedirectToIdentityProvider = notification =>
                    {
                        switch (notification.ProtocolMessage.RequestType)
                        {
                        case OpenIdConnectRequestType.Authentication:

                            if (notification.OwinContext.Response.StatusCode == 401)
                            {
                                if (IsAjaxRequest(notification.Request))
                                {
                                    if (Logger.IsInformationEnabled())
                                    {
                                        Logger.Information($"Request is made with AJAX and response is 401.");
                                    }

                                    notification.HandleResponse();
                                    return(Task.FromResult(0));
                                }

                                if (notification.OwinContext.Authentication.User.Identity.IsAuthenticated)
                                {
                                    if (Logger.IsInformationEnabled())
                                    {
                                        Logger.Information($"Request response code would be 401 but user '{notification.OwinContext.Authentication.User.Identity.Name}' is authenticated, switching response code to 403 (forbidden).");
                                    }

                                    notification.OwinContext.Response.StatusCode = 403;
                                    notification.HandleResponse();
                                    return(Task.FromResult(0));
                                }
                            }

                            break;

                        case OpenIdConnectRequestType.Logout:

                            if (notification.OwinContext.Authentication.User.Identity.IsAuthenticated)
                            {
                                Logger.Information($"User is logging out. User: {notification.OwinContext.Authentication.User.Identity.Name}.");
                            }

                            var idTokenHint = notification.OwinContext.Authentication.User.FindFirst(OpenIdConnectParameterNames.IdToken);

                            if (idTokenHint != null)
                            {
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.Debug($"Redirecting to Identity provider for logout with IdTokenHint.");
                                }

                                notification.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                            else
                            {
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.Debug($"Redirecting to Identity provider for logout without IdTokenHint.");
                                }
                            }

                            return(Task.FromResult(0));

                        case OpenIdConnectRequestType.Token:
                            break;

                        default:
                            break;
                        }

                        return(Task.FromResult(0));
                    },
                    AuthorizationCodeReceived = async notification =>
                    {
                        if (Logger.IsDebugEnabled())
                        {
                            Logger.Debug($"Authorization code received for sub: {notification.JwtSecurityToken.Subject}. Received claims: {GetClaimsAsString(notification.JwtSecurityToken.Claims)}.");
                        }
                        else
                        {
                            Logger.Information($"Authorization code received for sub: {notification.JwtSecurityToken.Subject}.");
                        }

                        OpenIdConnectConfiguration configuration = null;

                        try
                        {
                            configuration = await notification.Options.ConfigurationManager.GetConfigurationAsync(notification.Request.CallCancelled);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error($"Failed to get OpenIdConnectConfiguration. Cannot authorize the client with sub: {notification.JwtSecurityToken.Subject}.", ex);
                            throw;
                        }

                        var tokenClient = new TokenClient(configuration.TokenEndpoint, notification.Options.ClientId, notification.Options.ClientSecret, style: AuthenticationStyle.PostValues);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(notification.ProtocolMessage.Code, notification.RedirectUri, cancellationToken: notification.Request.CallCancelled);

                        if (tokenResponse.IsError)
                        {
                            Logger.Error($"There was an error retrieving the access token for sub: {notification.JwtSecurityToken.Subject}. Error: {tokenResponse.Error}. Error description: {tokenResponse.ErrorDescription}.");

                            notification.HandleResponse();

                            notification.Response.Write($"Error retrieving access token. {tokenResponse.ErrorDescription}.");
                            return;
                        }

                        if (string.IsNullOrWhiteSpace(tokenResponse.AccessToken))
                        {
                            Logger.Error($"Didn't receive access token for sub: {notification.JwtSecurityToken.Subject}.");

                            notification.HandleResponse();

                            notification.Response.Write($"Error, access token not received. {tokenResponse.ErrorDescription}.");
                            return;
                        }

                        if (!string.IsNullOrWhiteSpace(tokenResponse.IdentityToken))
                        {
                            try
                            {
                                JwtSecurityTokenHandler idTokenHandler = new JwtSecurityTokenHandler();
                                var parsedIdToken = idTokenHandler.ReadJwtToken(tokenResponse.IdentityToken);

                                if (string.Compare(parsedIdToken.Issuer, notification.JwtSecurityToken.Issuer, StringComparison.OrdinalIgnoreCase) != 0 ||
                                    string.Compare(parsedIdToken.Subject, notification.JwtSecurityToken.Subject, StringComparison.OrdinalIgnoreCase) != 0)
                                {
                                    Logger.Error($"Authorization endpoint id token 'sub' ({notification.JwtSecurityToken.Subject}) and 'iss' ({notification.JwtSecurityToken.Issuer}) claim values don't match with token endpoint 'sub' ({parsedIdToken.Subject}) and 'iss' ({parsedIdToken.Issuer}) claim values.");

                                    notification.HandleResponse();

                                    notification.Response.Write("Token endpoint identity token doesn't match autohorization endpoint returned identity token.");
                                    return;
                                }
                            }
                            catch (Exception ex)
                            {
                                Logger.Error($"Failed to validate token endpoint identity token against autohorization endpoint returned identity token.", ex);

                                notification.HandleResponse();

                                notification.Response.Write("Failed to validate token endpoint identity token against autohorization endpoint returned identity token.");
                                return;
                            }
                        }
                        else
                        {
                            Logger.Information($"Token endpoint didn't return identity token for sub: {notification.JwtSecurityToken.Subject}.");
                        }

                        var userInfoClient   = new UserInfoClient(configuration.UserInfoEndpoint);
                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        if (userInfoResponse.IsError)
                        {
                            Logger.Error($"There was an error retrieving the user information for sub: {notification.JwtSecurityToken.Subject}. Error: {userInfoResponse.Error}.");

                            notification.HandleResponse();

                            notification.Response.Write($"Error retrieving user information. {userInfoResponse.Error}.");
                            return;
                        }

                        if (Logger.IsDebugEnabled())
                        {
                            Logger.Debug($"Userinfo received for sub: {notification.JwtSecurityToken.Subject}. Received claims: {GetClaimsAsString(userInfoResponse.Claims)}.");
                        }
                        var authClaimsIdentity = new ClaimsIdentity(notification.AuthenticationTicket.Identity.AuthenticationType, "sub", JwtClaimTypes.Role);

                        List <Claim> roleClaims  = new List <Claim>();
                        List <Claim> otherClaims = new List <Claim>();

                        authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, "WebAdmins"));
                        authClaimsIdentity.AddClaim(new Claim(JwtClaimTypes.Role, "WebEditor"));

                        foreach (var c in userInfoResponse.Claims)
                        {
                            if (string.Compare(c.Type, "role", StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                roleClaims.Add(c);
                            }
                            else
                            {
                                otherClaims.Add(c);
                            }
                        }

                        string username = notification.JwtSecurityToken.Subject;
                        authClaimsIdentity.AddClaim(new Claim("sub", username));

                        bool addPublisherClaim = false;

                        authClaimsIdentity.AddClaim(new Claim(OpenIdConnectParameterNames.IdToken, notification.ProtocolMessage.IdToken));

                        notification.AuthenticationTicket = new AuthenticationTicket(authClaimsIdentity, notification.AuthenticationTicket.Properties);

                        Logger.Information($"Authenticated and logging in user '{GetFullName(authClaimsIdentity.Claims)}' (sub: {notification.JwtSecurityToken.Subject}).");

                        await ServiceLocator.Current.GetInstance <ISynchronizingUserService>().SynchronizeAsync(notification.AuthenticationTicket.Identity);
                    },
                    AuthenticationFailed = notification =>
                    {
                        Logger.Error($"Authentication failed: {notification.Exception.Message}");

                        notification.HandleResponse();
                        notification.Response.Write(notification.Exception.Message);
                        return(Task.FromResult(0));
                    },
                    SecurityTokenReceived = notification =>
                    {
                        if (Logger.IsDebugEnabled())
                        {
                            try
                            {
                                Logger.Debug($"Security token received. Code: '{notification.ProtocolMessage.Code}', IdToken: '{notification.ProtocolMessage.IdToken}'.");
                            }
                            catch (Exception ex)
                            {
                                Logger.Error($"Security token received. Failed to read Code and IdToken for debug logging.", ex);
                            }
                        }

                        return(Task.FromResult(0));
                    },
                    SecurityTokenValidated = notification =>
                    {
                        if (Logger.IsDebugEnabled())
                        {
                            try
                            {
                                Logger.Debug($"Security token validated for sub: {notification.AuthenticationTicket.Identity.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject)?.Value}.");
                            }
                            catch (Exception ex)
                            {
                                Logger.Error($"Security token validated. Failed to read values from protocol message for debug logging.", ex);
                            }
                        }

                        return(Task.FromResult(0));
                    },
                    MessageReceived = notification =>
                    {
                        if (Logger.IsDebugEnabled())
                        {
                            Logger.Debug($"Message received.");
                        }

                        return(Task.FromResult(0));
                    }
                }
            });

            app.UseStageMarker(PipelineStage.Authenticate);

            app.Map("/util/login.aspx", map =>
            {
                map.Run(ctx =>
                {
                    if (ctx.Authentication.User == null || !ctx.Authentication.User.Identity.IsAuthenticated)
                    {
                        ctx.Response.StatusCode = 401;
                    }
                    else
                    {
                        ctx.Response.Redirect("/");
                    }

                    return(Task.FromResult(0));
                });
            });

            app.Map("/util/logout.aspx", map =>
            {
                map.Run(ctx =>
                {
                    ctx.Authentication.SignOut();
                    return(Task.FromResult(0));
                });
            });
        }
예제 #19
0
        public void Configuration(IAppBuilder app)
        {
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = "mvc.owin.hybrid",
                Authority             = Constants.BaseAddress,
                RedirectUri           = "https://localhost:44300/",
                PostLogoutRedirectUri = "https://localhost:44300/",
                ResponseType          = "code id_token",
                Scope = "openid profile read write offline_access",

                SignInAsAuthenticationType = "Cookies",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            Constants.TokenEndpoint,
                            "mvc.owin.hybrid",
                            "secret");

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
                            n.Code, n.RedirectUri);

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(
                            new Uri(Constants.UserInfoEndpoint),
                            tokenResponse.AccessToken);

                        var userInfoResponse = await userInfoClient.GetAsync();

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType),
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #20
0
        public void Configuration(IAppBuilder app)
        {
            AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.Map("/identity", idsrvApp =>
            {
                idsrvApp.UseIdentityServer(new IdentityServerOptions
                {
                    SiteName           = "Embedded IdentityServer",
                    SigningCertificate = LoadCertificate(),

                    Factory = new IdentityServerServiceFactory()
                              .UseInMemoryUsers(Users.Get())
                              .UseInMemoryClients(Clients.Get())
                              .UseInMemoryScopes(Scopes.Get()),

                    AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions
                    {
                        EnablePostSignOutAutoRedirect = true,
                        IdentityProviders             = ConfigureIdentityProviders
                    }
                });
            });

            app.UseResourceAuthorization(new AuthorizationManager());

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority = "https://localhost:44319/identity",

                ClientId     = "mvc",
                Scope        = "openid profile roles sampleApi",
                ResponseType = "id_token token",
                RedirectUri  = "https://localhost:44319/",

                SignInAsAuthenticationType = "Cookies",
                UseTokenLifetime           = false,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var nid = new ClaimsIdentity(
                            n.AuthenticationTicket.Identity.AuthenticationType,
                            Constants.ClaimTypes.GivenName,
                            Constants.ClaimTypes.Role);

                        // get userinfo data
                        var userInfoClient = new UserInfoClient(
                            new Uri(n.Options.Authority + "/connect/userinfo"),
                            n.ProtocolMessage.AccessToken);

                        var userInfo = await userInfoClient.GetAsync();
                        userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Item1, ui.Item2)));

                        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        nid.AddClaim(new Claim("app_specific", "some data"));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            nid,
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }
                        return(Task.FromResult(0));
                    }
                }
            });
        }
        private async static Task <LoginResult> ValidateResponseAsync(AuthorizeResponse response, OidcSettings settings, OpenIdConnectConfiguration config, string expectedNonce, string verifier)
        {
            var tokenClaims = ValidateIdentityToken(response.IdentityToken, settings, config);

            if (tokenClaims == null)
            {
                return(new LoginResult {
                    ErrorMessage = "Invalid identity token."
                });
            }

            var nonce = tokenClaims.FirstOrDefault(c => c.Type == JwtClaimTypes.Nonce);

            if (nonce == null || !string.Equals(nonce.Value, expectedNonce, StringComparison.Ordinal))
            {
                return(new LoginResult {
                    ErrorMessage = "Inalid nonce."
                });
            }

            var codeHash = tokenClaims.FirstOrDefault(c => c.Type == JwtClaimTypes.AuthorizationCodeHash);

            if (codeHash == null || ValidateCodeHash(codeHash.Value, response.Code) == false)
            {
                return(new LoginResult {
                    ErrorMessage = "Invalid code."
                });
            }

            var provider = JwkNetExtensions.CreateProvider();
            var jwk      = provider.ToJsonWebKey();

            var tokenClient = new TokenClient(
                config.TokenEndpoint,
                settings.ClientId,
                settings.ClientSecret);

            var tokenResponse = await tokenClient.RequestAuthorizationCodePopAsync(
                code : response.Code,
                redirectUri : settings.RedirectUri,
                codeVerifier : settings.UsePkce?verifier : null,
                algorithm : jwk.Alg,
                key : jwk.ToJwkString());

            if (tokenResponse.IsError)
            {
                return(new LoginResult {
                    ErrorMessage = tokenResponse.Error
                });
            }

            var profileClaims = new List <Claim>();

            if (settings.LoadUserProfile)
            {
                var userInfoClient = new UserInfoClient(
                    new Uri(config.UserInfoEndpoint),
                    tokenResponse.AccessToken);

                var userInfoResponse = await userInfoClient.GetAsync();

                profileClaims = userInfoResponse.GetClaimsIdentity().Claims.ToList();
            }

            var principal = CreatePrincipal(tokenClaims, profileClaims, settings);

            return(new LoginResult
            {
                Success = true,
                User = principal,
                IdentityToken = response.IdentityToken,
                AccessToken = tokenResponse.AccessToken,
                RefreshToken = tokenResponse.RefreshToken,
                AccessTokenExpiration = DateTime.Now.AddSeconds(tokenResponse.ExpiresIn)
            });
        }
예제 #22
0
        public void ConfigureAuth(IAppBuilder app)
        {
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies",
                CookieHttpOnly     = true
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority             = ConfigurationManager.AppSettings["Authority"],
                ClientId              = ConfigurationManager.AppSettings["ClientId"],
                ClientSecret          = ConfigurationManager.AppSettings["ClientSecret"],
                RedirectUri           = ConfigurationManager.AppSettings["RedirectUri"],
                PostLogoutRedirectUri = ConfigurationManager.AppSettings["PostLogoutRedirectUri"],
                ResponseType          = OpenIdConnectResponseType.CodeIdToken,
                Scope = "openid profile api1.full_access",
                //Scope = "offline_access openid profile api1",
                RequireHttpsMetadata       = bool.Parse(ConfigurationManager.AppSettings["IsProduction"]),
                MetadataAddress            = ConfigurationManager.AppSettings["Authority"] + "/.well-known/openid-configuration",
                SignInAsAuthenticationType = "Cookies",
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        var disco = await DiscoveryClient.GetAsync(ConfigurationManager.AppSettings["Authority"]);
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            disco.TokenEndpoint,
                            ConfigurationManager.AppSettings["ClientId"],
                            ConfigurationManager.AppSettings["ClientSecret"]);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(disco.UserInfoEndpoint);

                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn).ToString()));
                        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken ?? ""));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                            n.AuthenticationTicket.Properties);
                    },
                    RedirectToIdentityProvider = n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #23
0
        public void Configuration(IAppBuilder app)
        {
            // Define que a chave do usuário vem da Claim "sub"
            AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
            // Desliga o mapeamento automático de Claims do asp.net, os nomes ficam como as
            // Claims do Acesso Cidadão..
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            // Configurar o OWIN para gerenciar autenticação usando Cookies
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            // Configurando para fazer autenticação usando OpenID Connect
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority = Constants.BaseAddress,
                ClientId  = Constants.ClientIdCorporativo,
                //ClientSecret = Constants.ClientSecretCorporativo,
                RedirectUri  = Constants.RedirectUriCorporativo,
                ResponseType = "id_token code",
                // A maioria desses scopes só está disponível para sistemas corporativos do estado
                // e precisa de permissão explicita da área responsável. Fazer requisição devidamente
                // fundamentada de porque a informação é necessária
                Scope = "openid nome email cpf dataNascimento filiacao permissoes roles offline_access api-teste",
                //Essas permissões só podem ser usadas em sistemas corporativos
                //Scope = "openid cpf nome email dataNascimento permissoes roles",

                // Configura o middleware do openid connect para usar o middleware configurado acima
                // para controlar a autenticação usando cookies
                SignInAsAuthenticationType = "Cookies",

                // Essa parte é totalmente opcional
                // Nesse exemplo a gente vai usar ela para apagar algumas claims que vem do Acesso Cidadão
                // e não queremos guardar e para setar o nome da identity
                // Mas também pode ser usada para fazer qualquer tipo de mapeamento das claims que vem do Acesso Cidadão
                // Por exemplo: Trocar o nome, por primeiro nome e sobrenome, mapear as permissões para outra
                // representação e assim por diante
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            Constants.TokenEndpoint,
                            Constants.ClientIdCorporativo,
                            Constants.ClientSecretCorporativo);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
                            n.Code, n.RedirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient   = new UserInfoClient(Constants.UserInfoEndpoint);
                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "nome", "role"),
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #24
0
        public void Configuration(IAppBuilder app)
        {
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });


            //app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            //{
            //    ClientId = "mvc.owin.hybrid",
            //    Authority = "http://localhost:44111/identity",
            //    RedirectUri = "https://localhost:44300/",
            //    PostLogoutRedirectUri = "https://localhost:44300/",
            //    ResponseType = "code id_token",
            //    Scope = "openid profile read write offline_access",

            //    SignInAsAuthenticationType = "Cookies",
            //    UseTokenLifetime = false,

            //    Notifications = new OpenIdConnectAuthenticationNotifications
            //    {
            //        SecurityTokenValidated = async n =>
            //        {
            //            var dddd = n;
            //            var nid = new ClaimsIdentity(
            //                n.AuthenticationTicket.Identity.AuthenticationType,
            //                IdentityServer3.Core.Constants.ClaimTypes.GivenName,
            //                IdentityServer3.Core.Constants.ClaimTypes.Role);

            //            // get userinfo data
            //            var userInfoClient = new UserInfoClient(
            //                new Uri(Constants.UserInfoEndpoint),
            //                n.ProtocolMessage.AccessToken);

            //            var userInfo = await userInfoClient.GetAsync();
            //            userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new System.Security.Claims.Claim(ui.Item1, ui.Item2)));

            //            // keep the id_token for logout
            //            nid.AddClaim(new System.Security.Claims.Claim("id_token", n.ProtocolMessage.IdToken));

            //            // add access token for sample API
            //            nid.AddClaim(new System.Security.Claims.Claim("access_token", n.ProtocolMessage.AccessToken));

            //            // keep track of access token expiration
            //            nid.AddClaim(new System.Security.Claims.Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

            //            // add some other app specific claim
            //            nid.AddClaim(new System.Security.Claims.Claim("app_specific", "some data"));

            //            n.AuthenticationTicket = new AuthenticationTicket(
            //                nid,
            //                n.AuthenticationTicket.Properties);
            //        },

            //        RedirectToIdentityProvider = n =>
            //        {
            //            if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
            //            {
            //                var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

            //                if (idTokenHint != null)
            //                {
            //                    n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
            //                }
            //            }

            //            return Task.FromResult(0);
            //        }
            //    }
            //});


            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = "mvc.owin.hybrid",
                Authority             = "http://localhost:44111/identity",
                RedirectUri           = "https://localhost:44300/",
                PostLogoutRedirectUri = "https://localhost:44300/",
                ResponseType          = "code id_token",
                Scope = "openid profile read write offline_access",

                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },

                SignInAsAuthenticationType = "Cookies",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            Constants.TokenEndpoint,
                            "mvc.owin.hybrid",
                            "secret");

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
                            n.Code, n.RedirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(
                            new Uri(Constants.UserInfoEndpoint),
                            tokenResponse.AccessToken);

                        var userInfoResponse = await userInfoClient.GetAsync();

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #25
0
        public void Configuration(IAppBuilder app)
        {
            string userInfoEndpoint =
                "https://localhost:44336/connect/userinfo";

            app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationType = "CookiesMedbullets",
                ExpireTimeSpan     = TimeSpan.FromMinutes(10),
                SlidingExpiration  = true
            });

            JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType         = "oidc",
                SignInAsAuthenticationType = "CookiesMedbullets",
                Authority             = "https://localhost:44336/",
                ClientId              = "implicit.medbullets",
                RedirectUri           = "http://localhost:5969/signin-oidc",
                PostLogoutRedirectUri = "http://localhost:5969/",
                ResponseType          = "id_token token",
                Scope            = "openid profile email profile.agent",
                UseTokenLifetime = false,
                Notifications    = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var claimsToExclude = new[]
                        {
                            "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
                        };

                        var claimsToKeep =
                            n.AuthenticationTicket.Identity.Claims
                            .Where(x => !claimsToExclude.Contains(x.Type))
                            .ToList();
                        claimsToKeep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));

                        if (n.ProtocolMessage.AccessToken != null)
                        {
                            claimsToKeep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));

                            var userInfoClient = new UserInfoClient(
                                new Uri(userInfoEndpoint),
                                n.ProtocolMessage.AccessToken); // Leverage Implicit flow we request User claims from endpoint usina access token!
                            // But access token came through front channel!
                            var userInfoResponse = await userInfoClient.GetAsync();
                            var userInfoClaims   = userInfoResponse.Claims
                                                   .Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token
                                                   .Select(x => new Claim(x.Item1, x.Item2));
                            claimsToKeep.AddRange(userInfoClaims);
                        }

                        var claimsIdentity = new ClaimsIdentity(
                            n.AuthenticationTicket.Identity.AuthenticationType,
                            "name", "role");
                        claimsIdentity.AddClaims(claimsToKeep);

                        n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(
                            claimsIdentity, n.AuthenticationTicket.Properties
                            );
                    },
                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType ==
                            OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idToken = n.OwinContext.Authentication
                                          .User.FindFirst("id_token")?.Value;
                            n.ProtocolMessage.IdTokenHint = idToken;
                        }
                        return(Task.FromResult(0));
                    }
                }
            });
            app.UseStageMarker(PipelineStage.Authenticate);
        }
예제 #26
0
        private async Task <LoginResult> ValidateResponseAsync(AuthorizeResponse response)
        {
            // id_token validieren
            var tokenClaims = ValidateIdentityToken(response.IdentityToken);

            if (tokenClaims == null)
            {
                return(new LoginResult {
                    ErrorMessage = "Invalid identity token."
                });
            }

            // nonce validieren
            var nonce = tokenClaims.FirstOrDefault(c => c.Type == JwtClaimTypes.Nonce);

            if (nonce == null || !string.Equals(nonce.Value, _nonce, StringComparison.Ordinal))
            {
                return(new LoginResult {
                    ErrorMessage = "Inalid nonce."
                });
            }

            // c_hash validieren
            var c_hash = tokenClaims.FirstOrDefault(c => c.Type == JwtClaimTypes.AuthorizationCodeHash);

            if (c_hash == null || ValidateCodeHash(c_hash.Value, response.Code) == false)
            {
                return(new LoginResult {
                    ErrorMessage = "Invalid code."
                });
            }

            _provider = JwkNetExtensions.CreateProvider();
            var jwk = _provider.ToJsonWebKey();

            // code eintauschen gegen tokens
            var tokenClient = new TokenClient(
                _config.TokenEndpoint,
                _settings.ClientId,
                _settings.ClientSecret);

            var tokenResponse = await tokenClient.RequestAuthorizationCodePopAsync(
                code : response.Code,
                redirectUri : _settings.RedirectUri,
                codeVerifier : _verifier,
                algorithm : jwk.Alg,
                key : jwk.ToJwkString());

            if (tokenResponse.IsError)
            {
                return(new LoginResult {
                    ErrorMessage = tokenResponse.Error
                });
            }

            // optional userinfo aufrufen
            var profileClaims = new List <Claim>();

            if (_settings.LoadUserProfile)
            {
                var userInfoClient = new UserInfoClient(
                    new Uri(_config.UserInfoEndpoint),
                    tokenResponse.AccessToken);

                var userInfoResponse = await userInfoClient.GetAsync();

                profileClaims = userInfoResponse.GetClaimsIdentity().Claims.ToList();
            }

            var principal = CreatePrincipal(tokenClaims, profileClaims);

            return(new LoginResult
            {
                Success = true,
                User = principal,
                IdentityToken = response.IdentityToken,
                AccessToken = tokenResponse.AccessToken,
                RefreshToken = tokenResponse.RefreshToken,
                AccessTokenExpiration = DateTime.Now.AddSeconds(tokenResponse.ExpiresIn)
            });
        }
예제 #27
0
        public void Configuration(IAppBuilder app)
        {
            AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();
            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Debug()
                         .WriteTo.File(@"c:\logs\sts.identityserver.txt")
                         .CreateLogger();

            IContainer container = AutofacConfig.ConfigureContainer();

            app.UseAutofacMiddleware(container);

            app.Map("/identity", coreApp =>
            {
                var factory = new IdentityServerServiceFactory()
                              .UseInMemoryClients(Clients.Get())
                              .UseInMemoryScopes(Scopes.Get());
                //.UseInMemoryUsers(Users.Get());


                factory.UserService = new Registration <IUserService, UserService>();

                var options = new IdentityServerOptions
                {
                    SiteName              = "Duy Tan Security Token Service",
                    SigningCertificate    = Certificate.Get(),
                    Factory               = factory,
                    RequireSsl            = false,
                    EnableWelcomePage     = true,
                    AuthenticationOptions = new IdentityServer3.Core.Configuration.AuthenticationOptions
                    {
                        EnablePostSignOutAutoRedirect = true,
                        EnableSignOutPrompt           = true
                    },
                    EventsOptions = new EventsOptions
                    {
                        RaiseSuccessEvents     = true,
                        RaiseErrorEvents       = true,
                        RaiseFailureEvents     = true,
                        RaiseInformationEvents = true
                    }
                };

                coreApp.UseIdentityServer(options);
            });

            app.UseResourceAuthorization(new AuthorizationManager());

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority          = "http://localhost:58891/identity",
                AuthenticationType = "oidc",
                ClientId           = "mvc",
                Scope        = "openid profile roles sampleApi",
                ResponseType = "id_token token",
                RedirectUri  = "http://localhost:58891",
                // PostLogoutRedirectUri = "http://localhost:58891",
                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                UseTokenLifetime           = false,

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var nid = new ClaimsIdentity(
                            n.AuthenticationTicket.Identity.AuthenticationType,
                            Constants.ClaimTypes.GivenName,
                            Constants.ClaimTypes.Role);

                        // get userinfo data
                        var userInfoClient = new UserInfoClient(
                            new Uri(n.Options.Authority + "/connect/userinfo"),
                            n.ProtocolMessage.AccessToken);

                        var userInfo = await userInfoClient.GetAsync();
                        userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Item1, ui.Item2)));

                        // keep the id_token for logout
                        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                        // add access token for sample API
                        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                        // keep track of access token expiration
                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        // add some other app specific claim
                        nid.AddClaim(new Claim("app_specific", "some data"));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            nid,
                            n.AuthenticationTicket.Properties);
                    },

                    AuthenticationFailed = n => {
                        return(Task.FromResult(0));
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #28
0
        public void Configuration(IAppBuilder app)
        {
            var stsServer    = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["sts-server"]) ? ConfigurationManager.AppSettings["sts-server"] : "";
            var redirectUri  = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["redirect-uri"]) ? ConfigurationManager.AppSettings["redirect-uri"] : "";
            var clientId     = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["client-id"]) ? ConfigurationManager.AppSettings["client-id"] : "";
            var clientSecret = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["client-secret"]) ? ConfigurationManager.AppSettings["client-secret"] : "";
            var clientScope  = !string.IsNullOrEmpty(ConfigurationManager.AppSettings["client-scope"]) ? ConfigurationManager.AppSettings["client-scope"] : "";

            JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary <string, string>();

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId              = clientId,
                Authority             = stsServer,
                RedirectUri           = redirectUri,
                PostLogoutRedirectUri = redirectUri,
                ResponseType          = "code id_token",
                Scope = clientScope,

                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },

                SignInAsAuthenticationType = "Cookies",

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            $"{stsServer}/connect/token/",
                            clientId,
                            clientSecret);

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
                            n.Code, n.RedirectUri);

                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient = new UserInfoClient(
                            new Uri($"{stsServer}/connect/userinfo/").ToString());

                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.Claims);

                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString(CultureInfo.CurrentCulture)));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        // if signing out, add the id_token_hint
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
        public void Configuration(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType         = "oidc",
                Authority                  = "http://localhost:5000", //ID Server
                ClientId                   = "hybrid_frame",
                ClientSecret               = "secret",
                ResponseType               = "id_token code",
                SignInAsAuthenticationType = "Cookies",
                RedirectUri                = "http://localhost:64760/signin-oidc",
                Scope = "openid offline_access email socialnetwork frameworkApi",
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                },

                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async n =>
                    {
                        // use the code to get the access and refresh token
                        var tokenClient = new TokenClient(
                            "http://localhost:5000/connect/token",
                            "hybrid_frame",
                            "secret");

                        var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);
                        if (tokenResponse.IsError)
                        {
                            throw new Exception(tokenResponse.Error);
                        }

                        // use the access token to retrieve claims from userinfo
                        var userInfoClient   = new UserInfoClient("http://localhost:5000/connect/userinfo");
                        var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                        // create new identity
                        var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                        id.AddClaims(userInfoResponse.Claims);
                        id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                        id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                        id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                        id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                        n.AuthenticationTicket = new AuthenticationTicket(
                            new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                            n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return(Task.FromResult(0));
                    }
                }
            });
        }
예제 #30
0
        // 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();

            var identityServer = Configuration["IdentityServerUrl"];

            app.UseCorrelationIdMiddleware(new CorrelationIdMiddlewareOptions());
            app.UseSerilogEnricherMiddleware();
            app.UseCors("default");

            var x = new Microsoft.IdentityModel.Tokens.TokenValidationParameters();

            var options = new IdentityServerAuthenticationOptions
            {
                Authority            = $"{identityServer}",
                ApiName              = "doc-stack-app-api",
                RequireHttpsMetadata = false,
                SaveToken            = true,

                JwtBearerEvents = new JwtBearerEvents()
                {
                    OnTokenValidated = async(context) =>
                    {
                        var principal = (ClaimsPrincipal)context.Ticket.Principal;
                        var identity  = (ClaimsIdentity)principal.Identity;

                        var accessToken = ((JwtSecurityToken)context.SecurityToken).RawData;
                        identity.AddClaim(new Claim("token", accessToken));
                        try
                        {
                            var discoveryClient = new DiscoveryClient(context.Options.Authority, null);
                            var doc             = await discoveryClient.GetAsync();

                            var json           = Newtonsoft.Json.JsonConvert.SerializeObject(doc, Formatting.Indented);
                            var userInfoClient = new UserInfoClient(doc.UserInfoEndpoint);

                            var response = await userInfoClient.GetAsync(accessToken);

                            json = Newtonsoft.Json.JsonConvert.SerializeObject(response, Formatting.Indented);
                            Console.WriteLine(json);
                            if (response.Claims != null)
                            {
                                identity.AddClaims(response.Claims);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"Claims could not be retrieved: {ex}");
                        }

                        context.Ticket = new AuthenticationTicket(principal, context.Ticket.Properties, context.Ticket.AuthenticationScheme);
                    }
                }
            };
            var options2 = IdentityServer4.AccessTokenValidation.CombinedAuthenticationOptions.FromIdentityServerAuthenticationOptions(options);

            options2.JwtBearerOptions.TokenValidationParameters.ValidIssuers = new List <string>()
            {
                identityServer
            };

            app.UseIdentityServerAuthentication(options2);

            app.UsePerformanceLog(new PerformanceLogOptions());
            app.UseHealthcheckEndpoint(new HealthCheckOptions()
            {
                Message = "Its alive"
            });

            app.UseMvc();

            // Enable middleware to serve generated Swagger as a JSON endpoint
            app.UseSwagger();

            // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
            app.UseSwaggerUi(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "doc-stack-app-api");

                c.ConfigureOAuth2("doc-stack-app-api-swagger", null, "swagger-ui-realm", "Swagger UI");
            });
        }