예제 #1
0
        public AuthorizationModule()
        {
            Get["/connect/authorize", runAsync : true] = async(parameters, cancellationToken) => {
                this.CreateNewCsrfToken();
                this.RequiresMSOwinAuthentication();

                // Note: when a fatal error occurs during the request processing, an OpenID Connect response
                // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler.
                // You can safely remove this part and let ASOS automatically handle the unrecoverable errors
                // by switching ApplicationCanDisplayErrors to false in Startup.cs.
                var response = OwinContext.GetOpenIdConnectResponse();
                if (response != null)
                {
                    return(View["Error.cshtml", response]);
                }

                // Extract the authorization request from the OWIN environment.
                var request = OwinContext.GetOpenIdConnectRequest();
                if (request == null)
                {
                    return(View["Error.cshtml", new OpenIdConnectMessage {
                                    Error = "invalid_request",
                                    ErrorDescription = "An internal error has occurred"
                                }]);
                }

                // Note: ASOS automatically ensures that an application corresponds to the client_id specified
                // in the authorization request by calling IOpenIdConnectServerProvider.ValidateAuthorizationRequest.
                // In theory, this null check shouldn't be needed, but a race condition could occur if you
                // manually removed the application details from the database after the initial check made by ASOS.
                var application = await GetApplicationAsync(request.ClientId, cancellationToken);

                if (application == null)
                {
                    return(View["Error.cshtml", new OpenIdConnectMessage {
                                    Error = "invalid_client",
                                    ErrorDescription = "Details concerning the calling client application cannot be found in the database"
                                }]);
                }

                // Note: in a real world application, you'd probably
                // prefer creating a specific view model.
                return(View["Authorize.cshtml", new { Application = application, Request = request }]);
            };

            Post["/connect/authorize/accept", runAsync : true] = async(parameters, cancellationToken) => {
                this.RequiresMSOwinAuthentication();
                this.ValidateCsrfToken();

                var response = OwinContext.GetOpenIdConnectResponse();
                if (response != null)
                {
                    return(View["Error.cshtml", response]);
                }

                var request = OwinContext.GetOpenIdConnectRequest();
                if (request == null)
                {
                    return(View["Error.cshtml", new OpenIdConnectMessage {
                                    Error = "invalid_request",
                                    ErrorDescription = "An internal error has occurred"
                                }]);
                }

                // Create a new ClaimsIdentity containing the claims that
                // will be used to create an id_token, a token or a code.
                var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType);

                foreach (var claim in OwinContext.Authentication.User.Claims)
                {
                    // Allow ClaimTypes.Name to be added in the id_token.
                    // ClaimTypes.NameIdentifier is automatically added, even if its
                    // destination is not defined or doesn't include "id_token".
                    // The other claims won't be visible for the client application.
                    if (claim.Type == ClaimTypes.Name)
                    {
                        claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken,
                                              OpenIdConnectConstants.Destinations.IdentityToken);
                    }

                    identity.AddClaim(claim);
                }

                var application = await GetApplicationAsync(request.ClientId, CancellationToken.None);

                if (application == null)
                {
                    return(View["Error.cshtml", new OpenIdConnectMessage {
                                    Error = "invalid_client",
                                    ErrorDescription = "Details concerning the calling client application cannot be found in the database"
                                }]);
                }

                // Create a new ClaimsIdentity containing the claims associated with the application.
                // Note: setting identity.Actor is not mandatory but can be useful to access
                // the whole delegation chain from the resource server (see ResourceModule.cs).
                identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType);
                identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID);

                identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName,
                                        OpenIdConnectConstants.Destinations.AccessToken,
                                        OpenIdConnectConstants.Destinations.IdentityToken);

                // Create a new authentication ticket holding the user identity.
                var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());

                // Set the list of scopes granted to the client application.
                // Note: this sample always grants the "openid", "email" and "profile" scopes
                // when they are requested by the client application: a real world application
                // would probably display a form allowing to select the scopes to grant.
                ticket.SetScopes(new[] {
                    /* openid: */ OpenIdConnectConstants.Scopes.OpenId,
                    /* email: */ OpenIdConnectConstants.Scopes.Email,
                    /* profile: */ OpenIdConnectConstants.Scopes.Profile,
                    /* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess
                }.Intersect(request.GetScopes()));

                // Set the resources servers the access token should be issued for.
                ticket.SetResources("resource_server");

                // This call will ask ASOS to serialize the specified identity to build appropriate tokens.
                // Note: you should always make sure the identities you return contain ClaimTypes.NameIdentifier claim.
                // In this sample, the identity always contains the name identifier returned by the external provider.
                OwinContext.Authentication.SignIn(ticket.Properties, ticket.Identity);

                return(HttpStatusCode.OK);
            };

            Post["/connect/authorize/deny"] = parameters => {
                this.RequiresMSOwinAuthentication();
                this.ValidateCsrfToken();

                var response = OwinContext.GetOpenIdConnectResponse();
                if (response != null)
                {
                    return(View["Error.cshtml", response]);
                }

                // Extract the authorization request from the cache, the query string or the request form.
                var request = OwinContext.GetOpenIdConnectRequest();
                if (request == null)
                {
                    return(View["Error.cshtml", new OpenIdConnectMessage {
                                    Error = "invalid_request",
                                    ErrorDescription = "An internal error has occurred"
                                }]);
                }

                // Notify ASOS that the authorization grant has been denied by the resource owner.
                // Note: OpenIdConnectServerHandler will automatically take care of redirecting
                // the user agent to the client application using the appropriate response_mode.
                OwinContext.Authentication.Forbid(OpenIdConnectServerDefaults.AuthenticationType);

                return(HttpStatusCode.Forbidden);
            };

            Get["/connect/logout", runAsync : true] = async(parameters, cancellationToken) => {
                var response = OwinContext.GetOpenIdConnectResponse();
                if (response != null)
                {
                    return(View["Error.cshtml", response]);
                }

                // When invoked, the logout endpoint might receive an unauthenticated request if the server cookie has expired.
                // When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved
                // using AuthenticateAsync or using User when the authorization server is declared as AuthenticationMode.Active.
                var identity = await OwinContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationType);

                // Extract the logout request from the OWIN environment.
                var request = OwinContext.GetOpenIdConnectRequest();
                if (request == null)
                {
                    return(View["Error.cshtml", new OpenIdConnectMessage {
                                    Error = "invalid_request",
                                    ErrorDescription = "An internal error has occurred"
                                }]);
                }

                return(View["Logout.cshtml", Tuple.Create(request, identity)]);
            };

            Post["/connect/logout"] = parameters => {
                this.ValidateCsrfToken();

                var response = OwinContext.GetOpenIdConnectResponse();
                if (response != null)
                {
                    return(View["Error.cshtml", response]);
                }

                // Ask the cookies middleware to delete the local cookie created
                // when the user agent is redirected from the external identity provider
                // after a successful authentication flow (e.g Google or Facebook) and
                // redirect the user agent to the post_logout_redirect_uri specified by the client application.
                OwinContext.Authentication.SignOut("ServerCookie", OpenIdConnectServerDefaults.AuthenticationType);

                return(HttpStatusCode.OK);
            };
        }
예제 #2
0
        public async Task <IActionResult> Exchange(OpenIdConnectRequest request)
        {
            if (request.IsPasswordGrantType())
            {
                var credentials = await _unitOfWork.Accounts
                                  .Include("User.Roles.Role.Permissions.Permission")
                                  .FirstOrDefaultAsync(c => c.Username == request.Username);

                if (credentials == null)
                {
                    return(Forbid(OpenIdConnectServerDefaults.AuthenticationScheme));
                }

                if (!BCrypt.Net.BCrypt.Verify(request.Password, credentials.Password))
                {
                    return(Forbid(OpenIdConnectServerDefaults.AuthenticationScheme));
                }

                // Create a new ClaimsIdentity holding the user identity.
                var identity = new ClaimsIdentity(
                    OpenIdConnectServerDefaults.AuthenticationScheme,
                    OpenIdConnectConstants.Claims.Name,
                    OpenIdConnectConstants.Claims.Role
                    );
                // Add a "sub" claim containing the user identifier, and attach
                // the "access_token" destination to allow OpenIddict to store it
                // in the access token, so it can be retrieved from your controllers.

                identity.AddClaim(OpenIdConnectConstants.Claims.Username, credentials.Username,
                                  OpenIdConnectConstants.Destinations.IdentityToken,
                                  OpenIdConnectConstants.Destinations.AccessToken);
                identity.AddClaim("id", credentials.User.Id.ToString(),
                                  OpenIdConnectConstants.Destinations.IdentityToken,
                                  OpenIdConnectConstants.Destinations.AccessToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.Subject, credentials.User.Id.ToString(), OpenIdConnectConstants.Destinations.IdentityToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.Name, credentials.User.Name, OpenIdConnectConstants.Destinations.IdentityToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName, credentials.User.LastName, OpenIdConnectConstants.Destinations.IdentityToken);
                identity.AddClaim(OpenIdConnectConstants.Claims.GivenName, credentials.User.FirstName, OpenIdConnectConstants.Destinations.IdentityToken);

                // ... add other claims, if necessary.
                var principal = new ClaimsPrincipal(identity);

                // Claims will not be associated with specific destinations by default, so we must indicate whether they should
                // be included or not in access and identity tokens.

                var authProperties = new AuthenticationProperties
                {
                    AllowRefresh = true
                };

                // Create a new authentication ticket for the user's principal
                var ticket = new AuthenticationTicket(
                    principal,
                    authProperties,
                    OpenIdConnectServerDefaults.AuthenticationScheme);

                var roles       = credentials.User.Roles.Select(r => r.Role);
                var permissions = roles.SelectMany(p => p.Permissions,
                                                   (role, permission) => permission.Permission.Name).ToList();

                // common scopes
                permissions.AddRange(new[]
                {
                    OpenIdConnectConstants.Scopes.OpenId,
                    OpenIdConnectConstants.Scopes.Email,
                    OpenIdConnectConstants.Scopes.Profile,
                    OpenIdConnectConstants.Scopes.OfflineAccess,
                    OpenIddictConstants.Scopes.Roles
                });

                // Include resources and scopes, as appropriate
                var scope = permissions.Intersect(request.GetScopes());

                // Set resource servers
                ticket.SetResources("onlineshop");
                ticket.SetScopes(scope);

                // Sign in the user
                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            // TODO add refresh token grant type
            else
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = "The specified grant type is not supported."
                }));
            }
        }
        public async Task <IActionResult> Accept(CancellationToken cancellationToken)
        {
            var response = HttpContext.GetOpenIdConnectResponse();

            if (response != null)
            {
                return(View("Error", response));
            }

            var request = HttpContext.GetOpenIdConnectRequest();

            if (request == null)
            {
                return(View("Error", new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.ServerError,
                    ErrorDescription = "An internal error has occurred"
                }));
            }

            // Create a new ClaimsIdentity containing the claims that
            // will be used to create an id_token, a token or a code.
            var identity = new ClaimsIdentity(
                OpenIdConnectServerDefaults.AuthenticationScheme,
                OpenIdConnectConstants.Claims.Name,
                OpenIdConnectConstants.Claims.Role);

            // Note: the "sub" claim is mandatory and an exception is thrown if this claim is missing.
            identity.AddClaim(
                new Claim(OpenIdConnectConstants.Claims.Subject, User.FindFirst(ClaimTypes.NameIdentifier).Value)
                .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken,
                                 OpenIdConnectConstants.Destinations.IdentityToken));

            identity.AddClaim(
                new Claim(OpenIdConnectConstants.Claims.Name, User.FindFirst(ClaimTypes.Name).Value)
                .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken,
                                 OpenIdConnectConstants.Destinations.IdentityToken));

            var application = await GetApplicationAsync(request.ClientId, cancellationToken);

            if (application == null)
            {
                return(View("Error", new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidClient,
                    ErrorDescription = "Details concerning the calling client application cannot be found in the database"
                }));
            }

            // Create a new authentication ticket holding the user identity.
            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                OpenIdConnectServerDefaults.AuthenticationScheme);

            // Set the list of scopes granted to the client application.
            // Note: this sample always grants the "openid", "email" and "profile" scopes
            // when they are requested by the client application: a real world application
            // would probably display a form allowing to select the scopes to grant.
            ticket.SetScopes(new[]
            {
                /* openid: */ OpenIdConnectConstants.Scopes.OpenId,
                /* email: */ OpenIdConnectConstants.Scopes.Email,
                /* profile: */ OpenIdConnectConstants.Scopes.Profile,
                /* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess
            }.Intersect(request.GetScopes()));

            // Set the resources servers the access token should be issued for.
            ticket.SetResources("resource_server");

            // Returning a SignInResult will ask ASOS to serialize the specified identity to build appropriate tokens.
            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }
예제 #4
0
//        [ValidateAntiForgeryToken]
        public async Task <IActionResult> Accept(CancellationToken cancellationToken)
        {
            var response = HttpContext.GetOpenIdConnectResponse();

            if (response != null)
            {
                return(View("Error", response));
            }

            var request = HttpContext.GetOpenIdConnectRequest();

            if (request == null)
            {
                return(View("Error", new OpenIdConnectMessage
                {
                    Error = OpenIdConnectConstants.Errors.ServerError,
                    ErrorDescription = "An internal error has occurred"
                }));
            }

            // Remove the authorization request from the user session.
            if (!string.IsNullOrEmpty(request.GetRequestId()))
            {
                HttpContext.Session.Remove("authorization-request:" + request.GetRequestId());
            }

            var scopes = request.GetScopes().ToList();
            var claims = HttpContext.User.Claims;

            var identity = _userManager.CreateIdentity(scopes, claims);

            var application = await _applicationRepository.GetByIdAsync(request.ClientId);

            if (application == null)
            {
                return(View("Error", new OpenIdConnectMessage
                {
                    Error = OpenIdConnectConstants.Errors.InvalidClient,
                    ErrorDescription =
                        "Details concerning the calling client application cannot be found in the database"
                }));
            }

            await _authorizationActionHandler.AddTrustedApplication(_userManager.GetCurrentUserId(), application.ApplicationId);

            identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
            identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationId);

            identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName,
                                    OpenIdConnectConstants.Destinations.AccessToken,
                                    OpenIdConnectConstants.Destinations.IdentityToken);

            // Create a new authentication ticket holding the user identity.
            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                OpenIdConnectServerDefaults.AuthenticationScheme);

            // Set the list of scopes granted to the client application.
            // Note: this sample always grants the "openid", "email" and "profile" scopes
            // when they are requested by the client application: a real world application
            // would probably display a form allowing to select the scopes to grant.
            ticket.SetScopes(new[]
            {
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.Email,
                OpenIdConnectConstants.Scopes.Profile,
                OpenIdConnectConstants.Scopes.OfflineAccess
            }.Intersect(request.GetScopes()));

            // Set the resources servers the access token should be issued for.
            ticket.SetResources("resource_server");

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }
        private async Task <AuthenticationTicket> DeserializeAccessTokenAsync(string token, OpenIdConnectRequest request)
        {
            var notification = new DeserializeAccessTokenContext(Context, Options, request, token)
            {
                DataFormat           = Options.AccessTokenFormat,
                SecurityTokenHandler = Options.AccessTokenHandler
            };

            // Note: ValidateAudience and ValidateLifetime are always set to false:
            // if necessary, the audience and the expiration can be validated
            // in InvokeIntrospectionEndpointAsync or InvokeTokenEndpointAsync.
            notification.TokenValidationParameters = new TokenValidationParameters {
                IssuerSigningKeys = Options.SigningCredentials.Select(credentials => credentials.SigningKey),
                ValidIssuer       = Context.GetIssuer(Options),
                ValidateAudience  = false,
                ValidateLifetime  = false
            };

            await Options.Provider.DeserializeAccessToken(notification);

            if (notification.HandledResponse || notification.Ticket != null)
            {
                notification.Ticket.SetUsage(OpenIdConnectConstants.Usages.AccessToken);

                return(notification.Ticket);
            }

            else if (notification.Skipped)
            {
                return(null);
            }

            var handler = notification.SecurityTokenHandler as ISecurityTokenValidator;

            if (handler == null)
            {
                return(notification.DataFormat?.Unprotect(token));
            }

            SecurityToken   securityToken;
            ClaimsPrincipal principal;

            try {
                if (!handler.CanReadToken(token))
                {
                    Options.Logger.LogDebug("The access token handler refused to read the token: {Token}", token);

                    return(null);
                }

                principal = handler.ValidateToken(token, notification.TokenValidationParameters, out securityToken);
            }

            catch (Exception exception) {
                Options.Logger.LogDebug("An exception occured when deserializing an access token: {Message}", exception.Message);

                return(null);
            }

            // Parameters stored in AuthenticationProperties are lost
            // when the identity token is serialized using a security token handler.
            // To mitigate that, they are inferred from the claims or the security token.
            var properties = new AuthenticationProperties {
                ExpiresUtc = securityToken.ValidTo,
                IssuedUtc  = securityToken.ValidFrom
            };

            var ticket = new AuthenticationTicket((ClaimsIdentity)principal.Identity, properties);

            var audiences = principal.FindAll(OpenIdConnectConstants.Claims.Audience);

            if (audiences.Any())
            {
                ticket.SetAudiences(audiences.Select(claim => claim.Value));
            }

            var presenters = principal.FindAll(OpenIdConnectConstants.Claims.AuthorizedParty);

            if (presenters.Any())
            {
                ticket.SetPresenters(presenters.Select(claim => claim.Value));
            }

            var scopes = principal.FindAll(OpenIdConnectConstants.Claims.Scope);

            if (scopes.Any())
            {
                ticket.SetScopes(scopes.Select(claim => claim.Value));
            }

            var identifier = principal.FindFirst(OpenIdConnectConstants.Claims.JwtId);

            if (identifier != null)
            {
                ticket.SetTicketId(identifier.Value);
            }

            var usage = principal.FindFirst(OpenIdConnectConstants.Claims.Usage);

            if (usage != null)
            {
                ticket.SetUsage(usage.Value);
            }

            var confidentiality = principal.FindFirst(OpenIdConnectConstants.Claims.ConfidentialityLevel);

            if (confidentiality != null)
            {
                ticket.SetProperty(OpenIdConnectConstants.Properties.ConfidentialityLevel, confidentiality.Value);
            }

            // Ensure the received ticket is an access token.
            if (!ticket.IsAccessToken())
            {
                Options.Logger.LogDebug("The received token was not an access token: {Token}.", token);

                return(null);
            }

            return(ticket);
        }
예제 #6
0
        public override async Task HandleTokenRequest(HandleTokenRequestContext context)
        {
            var isValid = false;

            if (context.Request.IsPasswordGrantType())
            {
                //Caso o usuário informe usuário e senha na requisição do token, você deve validar se é válido
                isValid = context.Request.Username == "teste" && context.Request.Password == "teste";
            }
            else if (context.Request.IsRefreshTokenGrantType())
            {
                //Caso seja um refresh_token, você deve verificar se o usuário continua tendo acesso
                //aos recursos e definir como válido ou não, note que não temos mais senha aqui
                //mas o token garante quem é o sujeito
                var login = context.Ticket.Principal.GetClaim(ClaimTypes.NameIdentifier);

                isValid = login == "teste";
            }

            if (!isValid)
            {
                //Aqui é a hora que define a requisição como inválida
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidGrant,
                    description: "Usuário/senha inválidos."
                    );
                return;
            }

            var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);

            //Aqui a gente cria os dados que queremos colocar no token
            //Como são dados de identificação não sensíveis, posso colocar no:
            //IdentityToken: Pode ser decriptado nos clients, serve para identificar em recursos externos
            //AccessToken: Token criptografado, que apenas o servidor que gerou (ou que possui a chave) possam decriptar as informações
            identity.AddClaim(ClaimTypes.Email, "*****@*****.**", Destinations.AccessToken, Destinations.IdentityToken);
            identity.AddClaim(ClaimTypes.GivenName, "Nome", Destinations.AccessToken, Destinations.IdentityToken);

            //Aqui são dados mais sensíveis, posso travar para enviar apenas no AccessToken
            identity.AddClaim(ClaimTypes.NameIdentifier, "teste", Destinations.AccessToken);
            identity.AddClaim(MyClaims.Perfil, MyPolicies.Vendedor, Destinations.AccessToken);

            //Coloca os dados no token
            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                context.Options.AuthenticationScheme
                );

            //Define os escopos do token, esta informação pode ser recebida no request e revalidada para enviar apenas o que o client pediu
            //Caso não vá precisar autenticar em outros serviços (99% das vezes) você pode suprimir o OpenId
            //Caso não queira permitir o refresh da autorização sem senha, pode suprimir o OfflineAccess
            ticket.SetScopes(
                Scopes.OpenId,
                Scopes.OfflineAccess
                );

            //Você também pode informar os recursos a que este usuário tem acesso, isto será enviado no Identity Token, para o client travar um menu por ex....
            //ticket.SetResources("ApiCadastro, ApiCliente, ApiVenda, ...");

            context.Validate(ticket);
        }
예제 #7
0
        public async override Task GrantResourceOwnerCredentials(
            GrantResourceOwnerCredentialsContext context)
        {
            _authService = (IAuthService)context.HttpContext.RequestServices.GetService(typeof(IAuthService));
            Client client        = _authService.FindClient(context.ClientId);
            string allowedOrigin = string.Empty;

            allowedOrigin = client.AllowedOrigin == null ? "*" : client.AllowedOrigin;

            //comentado pois está dando conflito com cors adicionado anteriormente
            //context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

            var user = await _authService.GetUsuarioEmail(context.UserName);

            var valid = await _authService.CheckPasswordAsync(user, context.Password);

            if (valid)
            {
                int casaId = await _authService.GetCasaSelecionada(user);

                //verifica se usuario esta bloqueado para aquela casa
                if (_authService.AcessoUsuarioBloqueado(user.Id, casaId))
                {
                    //tenta obter acesso em outra casa
                    int novaCasaSelec = _authService.TentaSelecOutraCasa(user.Id, casaId);

                    if (novaCasaSelec == 0)
                    {
                        context.Reject("O seu acesso foi bloqueado");
                        return;
                    }

                    casaId = novaCasaSelec;
                }

                var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);

                foreach (var claim in  _authService.GetClaims(user, casaId))
                {
                    identity.AddClaim(claim.Type, claim.Value, "access_token", "id_token");
                }

                identity.AddClaim("casa", casaId.ToString(), "access_token", "id_token");

                identity.AddClaim(ClaimTypes.NameIdentifier, user.Id, "access_token", "id_token");

                identity.AddClaim(ClaimTypes.Name, user.UserName, "access_token", "id_token");


                var principal = new ClaimsPrincipal(identity);

                var props = new AuthenticationProperties(new Dictionary <string, string>
                {
                    {
                        "client_id", (context.ClientId == null) ? string.Empty : context.ClientId
                    },
                    {
                        "userName", context.UserName
                    }
                });

                var ticket = new AuthenticationTicket(principal, props, OpenIdConnectServerDefaults.AuthenticationScheme);

                List <string> scopes = new List <string>();
                if (context.Request.HasScope("offline_access"))
                {
                    scopes.Add("offline_access");
                }

                ticket.SetScopes(scopes);

                context.Validate(ticket);
            }
        }
예제 #8
0
        public override async Task GrantResourceOwnerCredentials([NotNull] GrantResourceOwnerCredentialsContext context)
        {
            var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TUser, TApplication> >();

            var user = await services.Users.FindByNameAsync(context.UserName);

            if (user == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidGrant,
                    description: "Invalid credentials.");

                return;
            }

            // Ensure the user is allowed to sign in.
            if (!await services.SignIn.CanSignInAsync(user))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidGrant,
                    description: "The user is not allowed to sign in.");

                return;
            }

            // Ensure the user is not already locked out.
            if (services.Users.SupportsUserLockout && await services.Users.IsLockedOutAsync(user))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidGrant,
                    description: "Account locked out.");

                return;
            }

            // Ensure the password is valid.
            if (!await services.Users.CheckPasswordAsync(user, context.Password))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidGrant,
                    description: "Invalid credentials.");

                if (services.Users.SupportsUserLockout)
                {
                    await services.Users.AccessFailedAsync(user);

                    // Ensure the user is not locked out.
                    if (await services.Users.IsLockedOutAsync(user))
                    {
                        context.Reject(
                            error: OpenIdConnectConstants.Errors.InvalidGrant,
                            description: "Account locked out.");
                    }
                }

                return;
            }

            if (services.Users.SupportsUserLockout)
            {
                await services.Users.ResetAccessFailedCountAsync(user);
            }

            // Reject the token request if two-factor authentication has been enabled by the user.
            if (services.Users.SupportsUserTwoFactor && await services.Users.GetTwoFactorEnabledAsync(user))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidGrant,
                    description: "Two-factor authentication is required for this account.");

                return;
            }

            // Return an error if the username corresponds to the registered
            // email address and if the "email" scope has not been requested.
            if (context.Request.HasScope(OpenIdConnectConstants.Scopes.Profile) &&
                !context.Request.HasScope(OpenIdConnectConstants.Scopes.Email) &&
                string.Equals(await services.Users.GetUserNameAsync(user),
                              await services.Users.GetEmailAsync(user),
                              StringComparison.OrdinalIgnoreCase))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The 'email' scope is required.");

                return;
            }

            var identity = await services.Applications.CreateIdentityAsync(user, context.Request.GetScopes());

            Debug.Assert(identity != null);

            // Create a new authentication ticket holding the user identity.
            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                context.Options.AuthenticationScheme);

            ticket.SetResources(context.Request.GetResources());
            ticket.SetScopes(context.Request.GetScopes());

            context.Validate(ticket);
        }
예제 #9
0
        private static TestServer CreateAuthorizationServer(Action <OpenIddictBuilder> configuration = null)
        {
            var builder = new WebHostBuilder();

            builder.UseEnvironment("Testing");

            builder.ConfigureLogging(options => options.AddDebug());

            builder.ConfigureServices(services =>
            {
                services.AddOptions();
                services.AddDistributedMemoryCache();

                // Note: the following client_id/client_secret are fake and are only
                // used to test the metadata returned by the discovery endpoint.
                services.AddAuthentication()
                .AddFacebook(options =>
                {
                    options.ClientId     = "16018790-E88E-4553-8036-BB342579FF19";
                    options.ClientSecret = "3D6499AF-5607-489B-815A-F3ACF1617296";
                    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })

                .AddGoogle(options =>
                {
                    options.ClientId     = "BAF437A5-87FA-4D06-8EFD-F9BA96CCEDC4";
                    options.ClientSecret = "27DF07D3-6B03-4EE0-95CD-3AC16782216B";
                    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                });

                // Replace the default OpenIddict managers.
                services.AddSingleton(CreateApplicationManager());
                services.AddSingleton(CreateAuthorizationManager());
                services.AddSingleton(CreateScopeManager());
                services.AddSingleton(CreateTokenManager());

                services.AddOpenIddict(options =>
                {
                    // Disable the transport security requirement during testing.
                    options.DisableHttpsRequirement();

                    // Enable the tested endpoints.
                    options.EnableAuthorizationEndpoint(AuthorizationEndpoint)
                    .EnableIntrospectionEndpoint(IntrospectionEndpoint)
                    .EnableLogoutEndpoint(LogoutEndpoint)
                    .EnableRevocationEndpoint(RevocationEndpoint)
                    .EnableTokenEndpoint(TokenEndpoint)
                    .EnableUserinfoEndpoint(UserinfoEndpoint);

                    // Enable the tested flows.
                    options.AllowAuthorizationCodeFlow()
                    .AllowClientCredentialsFlow()
                    .AllowImplicitFlow()
                    .AllowPasswordFlow()
                    .AllowRefreshTokenFlow();

                    // Register the X.509 certificate used to sign the identity tokens.
                    options.AddSigningCertificate(
                        assembly: typeof(OpenIddictProviderTests).GetTypeInfo().Assembly,
                        resource: "OpenIddict.Tests.Certificate.pfx",
                        password: "******");

                    // Note: overriding the default data protection provider is not necessary for the tests to pass,
                    // but is useful to ensure unnecessary keys are not persisted in testing environments, which also
                    // helps make the unit tests run faster, as no registry or disk access is required in this case.
                    options.UseDataProtectionProvider(new EphemeralDataProtectionProvider(new LoggerFactory()));

                    // Run the configuration delegate
                    // registered by the unit tests.
                    configuration?.Invoke(options);
                });
            });

            builder.Configure(app =>
            {
                app.UseStatusCodePages(context =>
                {
                    context.HttpContext.Response.Headers[HeaderNames.ContentType] = "application/json";

                    return(context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(new
                    {
                        error_custom = OpenIdConnectConstants.Errors.InvalidRequest
                    })));
                });

                app.Use(next => context =>
                {
                    if (context.Request.Path != "/authorize-status-code-middleware" &&
                        context.Request.Path != "/logout-status-code-middleware")
                    {
                        var feature     = context.Features.Get <IStatusCodePagesFeature>();
                        feature.Enabled = false;
                    }

                    return(next(context));
                });

                app.UseAuthentication();

                app.Run(context =>
                {
                    var request = context.GetOpenIdConnectRequest();
                    if (request.IsAuthorizationRequest() || request.IsTokenRequest())
                    {
                        var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
                        identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Magnifique");

                        var ticket = new AuthenticationTicket(
                            new ClaimsPrincipal(identity),
                            new AuthenticationProperties(),
                            OpenIdConnectServerDefaults.AuthenticationScheme);

                        ticket.SetScopes(request.GetScopes());

                        if (request.HasParameter("attach-authorization"))
                        {
                            ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, "1AF06AB2-A0FC-4E3D-86AF-E04DA8C7BE70");
                        }

                        if (request.HasParameter("do-not-flow-original-properties"))
                        {
                            var properties = new AuthenticationProperties();
                            properties.SetProperty("custom_property_in_new_ticket", "new_value");

                            return(context.SignInAsync(ticket.AuthenticationScheme, ticket.Principal, properties));
                        }

                        return(context.SignInAsync(ticket.AuthenticationScheme, ticket.Principal, ticket.Properties));
                    }

                    else if (request.IsLogoutRequest())
                    {
                        return(context.SignOutAsync(OpenIdConnectServerDefaults.AuthenticationScheme));
                    }

                    else if (request.IsUserinfoRequest())
                    {
                        context.Response.Headers[HeaderNames.ContentType] = "application/json";

                        return(context.Response.WriteAsync(JsonConvert.SerializeObject(new
                        {
                            access_token = request.AccessToken,
                            sub = "Bob le Bricoleur"
                        })));
                    }

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

            return(new TestServer(builder));
        }
예제 #10
0
        // Implementing HandleTokenRequest to issue an authentication ticket containing the user claims
        public override async Task HandleTokenRequest(HandleTokenRequestContext context)
        {
            // Only handle grant_type=password requests and let ASOS
            // process grant_type=refresh_token requests automatically.
            if (context.Request.IsPasswordGrantType())
            {
                // Get user login data.
                var loginDetails = await LoginProvider.GetEntity(context.Request.Username);

                if (loginDetails == null)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidGrant,
                        description: "Invalid credentials.");
                    return;
                }
                if (loginDetails.UniqueId != context.Request.Username)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidGrant,
                        description: "Invalid credentials.");
                    return;
                }

                // Get user data
                var user = await RavenDatabaseProvider.GetEntity <User>(loginDetails.UserId);

                if (user == null)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidGrant,
                        description: "Invalid username or password.");
                    return;
                }
                // Ensure the user is allowed to sign in.
                if (await UserProvider.IsBannedAsync(user))
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidGrant,
                        description: "The specified user is not allowed to sign in.");
                    return;
                }

                // Ensure the user is not already locked out.
                if (LoginProvider.SupportsUserLockout && await LoginProvider.IsLockedOutAsync(loginDetails))
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidGrant,
                        description: "Invalid credentials.");
                    return;
                }

                // Ensure the password is valid.
                if (!LoginProvider.IsPasswordCorrect(loginDetails, context.Request.Password))
                {
                    if (LoginProvider.SupportsUserLockout)
                    {
                        // Increment lock out count
                        await LoginProvider.AccessFailedAsync(loginDetails);
                    }
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidGrant,
                        description: "Invalid credentials.");
                    return;
                }
                if (LoginProvider.SupportsUserLockout)
                {
                    // Reset lock out data
                    await LoginProvider.ResetAccessFailedCountAsync(loginDetails);
                }

                var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);

                // Note: the subject claim is always included in both identity and
                // access tokens, even if an explicit destination is not specified.
                identity.AddClaim(OpenIdConnectConstants.Claims.Subject, loginDetails.UserId);

                // Add user-id
                identity.AddClaim(ClaimTypes.Name, user.Id,
                                  OpenIdConnectConstants.Destinations.AccessToken);

                // Add user-role
                identity.AddClaim(ClaimTypes.Role, user.Type.ToString(),
                                  OpenIdConnectConstants.Destinations.AccessToken);

                // Create a new authentication ticket holding the user identity.
                var ticket = new AuthenticationTicket(
                    new ClaimsPrincipal(identity),
                    new AuthenticationProperties(),
                    OpenIdConnectServerDefaults.AuthenticationScheme);

                // Set the list of scopes granted to the client application.
                // (specify offline_access to issue a refresh token).
                ticket.SetScopes(OpenIdConnectConstants.Scopes.OfflineAccess);

                context.Validate(ticket);
            }

            return;
        }
예제 #11
0
        private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, ApplicationUser user)
        {
            // Create a new ClaimsPrincipal containing the claims that
            // will be used to create an id_token, a token or a code.
            var principal = await _signInManager.CreateUserPrincipalAsync(user);

            var identity = (ClaimsIdentity)principal.Identity;

            // !! ADDING FIELD: this will include FavColor in generated JWT access tokens & id tokens
            var favColorClaim = new Claim("favColor", user.FavColor?.ToString() ?? "", ClaimValueTypes.String);

            favColorClaim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken);
            identity.AddClaim(favColorClaim);

            // Create a new authentication ticket holding the user identity.
            var ticket = new AuthenticationTicket(principal,
                                                  new AuthenticationProperties(),
                                                  OpenIdConnectServerDefaults.AuthenticationScheme);

            // Set the list of scopes granted to the client application.
            ticket.SetScopes(new[]
            {
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.Email,
                OpenIdConnectConstants.Scopes.Profile,
                OpenIddictConstants.Scopes.Roles
            }.Intersect(request.GetScopes()));

            ticket.SetResources(_configuration["Cierge:Audience"]);

            // Note: by default, claims are NOT automatically included in the access and identity tokens.
            // To allow OpenIddict to serialize them, you must attach them a destination, that specifies
            // whether they should be included in access tokens, in identity tokens or in both.

            foreach (var claim in ticket.Principal.Claims)
            {
                // Never include the security stamp in the access and identity tokens, as it's a secret value.
                if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType)
                {
                    continue;
                }

                var destinations = new List <string>
                {
                    OpenIdConnectConstants.Destinations.AccessToken
                };

                // Only add the iterated claim to the id_token if the corresponding scope was granted to the client application.
                // The other claims will only be added to the access_token, which is encrypted when using the default format.
                if ((claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) ||
                    (claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) ||
                    (claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles)))
                {
                    destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);
                }

                claim.SetDestinations(destinations);
            }


            return(ticket);
        }
예제 #12
0
        public virtual async Task <IActionResult> Accept()
        {
            // Note: when a fatal error occurs during the request processing, an OpenID Connect response
            // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler.
            // In this case, the OpenID Connect request is null and cannot be used.
            // When the user agent can be safely redirected to the client application,
            // OpenIdConnectServerHandler automatically handles the error and MVC is not invoked.
            // You can safely remove this part and let AspNet.Security.OpenIdConnect.Server automatically
            // handle the unrecoverable errors by switching ApplicationCanDisplayErrors to false.
            var response = HttpContext.GetOpenIdConnectResponse();

            if (response != null)
            {
                return(View("Error", response));
            }

            // Extract the authorization request from the cache,
            // the query string or the request form.
            var request = HttpContext.GetOpenIdConnectRequest();

            if (request == null)
            {
                return(View("Error", new OpenIdConnectMessage {
                    Error = OpenIdConnectConstants.Errors.ServerError,
                    ErrorDescription = "An internal error has occurred"
                }));
            }

            // Retrieve the user data using the unique identifier.
            var user = await Manager.FindByIdAsync(User.GetUserId());

            if (user == null)
            {
                return(View("Error", new OpenIdConnectMessage {
                    Error = OpenIdConnectConstants.Errors.ServerError,
                    ErrorDescription = "An internal error has occurred"
                }));
            }

            // Create a new ClaimsIdentity containing the claims that
            // will be used to create an id_token, a token or a code.
            var identity = await Manager.CreateIdentityAsync(user, request.GetScopes());

            Debug.Assert(identity != null);

            // Note: AspNet.Security.OpenIdConnect.Server automatically ensures an application
            // corresponds to the client_id specified in the authorization request using
            // IOpenIdConnectServerProvider.ValidateClientRedirectUri (see OpenIddictProvider.cs).
            var application = await Manager.FindApplicationByIdAsync(request.ClientId);

            // In theory, this null check is thus not strictly necessary. That said, a race condition
            // and a null reference exception could appear here if you manually removed the application
            // details from the database after the initial check made by AspNet.Security.OpenIdConnect.Server.
            if (application == null)
            {
                return(View("Error", new OpenIdConnectMessage {
                    Error = OpenIdConnectConstants.Errors.InvalidClient,
                    ErrorDescription = "Details concerning the calling client application cannot be found in the database"
                }));
            }

            // Create a new ClaimsIdentity containing the claims associated with the application.
            // Note: setting identity.Actor is not mandatory but can be useful to access
            // the whole delegation chain from the resource server (see ResourceController.cs).
            identity.Actor = new ClaimsIdentity(Options.AuthenticationScheme);
            identity.Actor.AddClaim(ClaimTypes.NameIdentifier, request.ClientId);

            identity.Actor.AddClaim(ClaimTypes.Name, await Manager.GetDisplayNameAsync(application),
                                    OpenIdConnectConstants.Destinations.AccessToken,
                                    OpenIdConnectConstants.Destinations.IdentityToken);

            // Create a new authentication ticket holding the user identity.
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), null, Options.AuthenticationScheme);

            ticket.SetResources(request.GetResources());
            ticket.SetScopes(request.GetScopes());

            // This call will instruct AspNet.Security.OpenIdConnect.Server to serialize
            // the specified identity to build appropriate tokens (id_token and token).
            // Note: you should always make sure the identities you return contain either
            // a 'sub' or a 'ClaimTypes.NameIdentifier' claim. In this case, the returned
            // identities always contain the name identifier returned by the external provider.
            await HttpContext.Authentication.SignInAsync(ticket.AuthenticationScheme, ticket.Principal, ticket.Properties);

            return(new EmptyResult());
        }
예제 #13
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();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();

                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
                    HotModuleReplacement = false // Aurelia Webpack Plugin HMR currently has issues. Leave this set to false.
                });
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseOpenIdConnectServer(options =>
            {
                // Enable the token endpoint.
                options.TokenEndpointPath = "/api/token";

                // Implement OnValidateTokenRequest to support flows using the token endpoint.
                options.Provider.OnValidateTokenRequest = context =>
                {
                    // Reject token requests that don't use grant_type=password or grant_type=refresh_token.
                    if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType())
                    {
                        context.Reject(
                            error: OpenIdConnectConstants.Errors.UnsupportedGrantType,
                            description: "Only grant_type=password and refresh_token " +
                            "requests are accepted by this server.");

                        return(Task.FromResult(0));
                    }

                    // Note: you can skip the request validation when the client_id
                    // parameter is missing to support unauthenticated token requests.
                    // if (string.IsNullOrEmpty(context.ClientId))
                    // {
                    //     context.Skip();
                    //
                    //     return Task.FromResult(0);
                    // }

                    // Note: to mitigate brute force attacks, you SHOULD strongly consider applying
                    // a key derivation function like PBKDF2 to slow down the secret validation process.
                    // You SHOULD also consider using a time-constant comparer to prevent timing attacks.
                    if (string.Equals(context.ClientId, "client_id", StringComparison.Ordinal) &&
                        string.Equals(context.ClientSecret, "client_secret", StringComparison.Ordinal))
                    {
                        context.Validate();
                    }

                    // Note: if Validate() is not explicitly called,
                    // the request is automatically rejected.
                    return(Task.FromResult(0));
                };

                // Implement OnHandleTokenRequest to support token requests.
                options.Provider.OnHandleTokenRequest = context =>
                {
                    // Only handle grant_type=password token requests and let the
                    // OpenID Connect server middleware handle the other grant types.
                    if (context.Request.IsPasswordGrantType())
                    {
                        // Implement context.Request.Username/context.Request.Password validation here.
                        // Note: you can call context Reject() to indicate that authentication failed.
                        // Using password derivation and time-constant comparer is STRONGLY recommended.
                        if (!string.Equals(context.Request.Username, "Bob", StringComparison.Ordinal) ||
                            !string.Equals(context.Request.Password, "P@ssw0rd", StringComparison.Ordinal))
                        {
                            context.Reject(
                                error: OpenIdConnectConstants.Errors.InvalidGrant,
                                description: "Invalid user credentials.");

                            return(Task.FromResult(0));
                        }

                        var identity = new ClaimsIdentity(context.Options.AuthenticationScheme,
                                                          OpenIdConnectConstants.Claims.Name,
                                                          OpenIdConnectConstants.Claims.Role);

                        // Add the mandatory subject/user identifier claim.
                        identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "[unique id]");

                        // By default, claims are not serialized in the access/identity tokens.
                        // Use the overload taking a "destinations" parameter to make sure
                        // your claims are correctly inserted in the appropriate tokens.
                        identity.AddClaim("urn:customclaim", "value",
                                          OpenIdConnectConstants.Destinations.AccessToken,
                                          OpenIdConnectConstants.Destinations.IdentityToken);

                        var ticket = new AuthenticationTicket(
                            new ClaimsPrincipal(identity),
                            new AuthenticationProperties(),
                            context.Options.AuthenticationScheme);

                        // Call SetScopes with the list of scopes you want to grant
                        // (specify offline_access to issue a refresh token).
                        ticket.SetScopes(
                            OpenIdConnectConstants.Scopes.Profile,
                            OpenIdConnectConstants.Scopes.OfflineAccess);

                        context.Validate(ticket);
                    }

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

                options.SigningCredentials.AddCertificate("D1229DEE962DD394BC3659DED38E4B56629EB943");
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });
        }
        private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, Users _user)
        {
            // Create a new ClaimsPrincipal containing the claims that
            // will be used to create an id_token, a token or a code.
            // var principal = await _signInManager.CreateUserPrincipalAsync(user);

            var identity = new ClaimsIdentity(
                OpenIddictServerDefaults.AuthenticationScheme,
                OpenIdConnectConstants.Claims.Name,
                OpenIdConnectConstants.Claims.Role);

            // Add a "sub" claim containing the user identifier, and attach
            // the "access_token" destination to allow OpenIddict to store it
            // in the access token, so it can be retrieved from your controllers.
            //Users _user = PatrolUserManager.GetUserByUserName(user.UserName);

            identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                              _user.Userid.ToString(),
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Name, _user.Username,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim("userName", _user.Username,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim("empDisplayName", _user.Name,
                              OpenIdConnectConstants.Destinations.AccessToken);
            //   identity.AddClaim("mNO", "",
            // OpenIdConnectConstants.Destinations.AccessToken);
            //   identity.AddClaim("empDeptCode", "",
            //OpenIdConnectConstants.Destinations.AccessToken);
            //   identity.AddClaim("empDeptName", "",
            //OpenIdConnectConstants.Destinations.AccessToken);

            var userRoles = PatrolUserManager.GetRolesByUserId(_user.Userid);

            foreach (var role in userRoles)
            {
                identity.AddClaim(ClaimTypes.Role, role,
                                  OpenIdConnectConstants.Destinations.AccessToken);
            }
            var userLeftNavigation =
                identity.AddClaim("userLeftNavigation", PatrolUserManager.FetchLeftNavigationByUserId(_user.Userid),
                                  OpenIdConnectConstants.Destinations.AccessToken);

            identity.AddClaim("configuration", PatrolUserManager.GetUserPreferenceByUserId(_user.Userid, userRoles),
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim("role", JsonConvert.SerializeObject(userRoles.ToArray()),
                              OpenIdConnectConstants.Destinations.AccessToken);
            //identity.AddClaim(ClaimTypes.Role, "ViewPatrolCarsRole",
            //   OpenIdConnectConstants.Destinations.AccessToken);
            //identity.AddClaim(ClaimTypes.Role, "ViewPatrolCarsRole",
            //  OpenIdConnectConstants.Destinations.AccessToken);

            // ... add other claims, if necessary.
            var principal = new ClaimsPrincipal(identity);

            // Create a new authentication ticket holding the user identity.
            var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIddictServerDefaults.AuthenticationScheme);


            //if (!request.IsRefreshTokenGrantType())
            //{
            // Set the list of scopes granted to the client application.
            // Note: the offline_access scope must be granted
            // to allow OpenIddict to return a refresh token.
            ticket.SetScopes(new[]
            {
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.Email,
                OpenIdConnectConstants.Scopes.OfflineAccess,
                OpenIddictConstants.Scopes.Roles
            }.Intersect(request.GetScopes()));

            // Note: by default, claims are NOT automatically included in the access and identity tokens.
            // To allow OpenIddict to serialize them, you must attach them a destination, that specifies
            // whether they should be included in access tokens, in identity tokens or in both.
            foreach (var claim in ticket.Principal.Claims)
            {
                //// Never include the security stamp in the access and identity tokens, as it's a secret value.
                //if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType)
                //    continue;


                var destinations = new List <string> {
                    OpenIdConnectConstants.Destinations.AccessToken
                };
                destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);

                claim.SetDestinations(destinations);
            }



            return(ticket);
        }
예제 #15
0
        public async Task <IActionResult> Accept(CancellationToken cancellationToken)
        {
            ApplicationUser au = await _userManager.GetUserAsync(HttpContext.User);

            if (au == null)
            {
                return(View("Error", new AuthorizeErrorViewModel()
                {
                    Error = "No such user",
                    ErrorDescription = "Failed to find specified user"
                }));
            }


            OpenIdConnectRequest request = HttpContext.GetOpenIdConnectRequest();

            ClaimsIdentity identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role);

            // We serialize the user_id so we can determine which user the caller of this token is
            string userid = _userManager.GetUserId(HttpContext.User);

            identity.AddClaim(
                new Claim(OpenIdConnectConstants.Claims.Subject, userid)
                .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken));

            // We serialize the grant_type so we can user discriminate rate-limits. AuthorizationCode grants have the highest rate-limit allowance
            identity.AddClaim(
                new Claim("grant_type", OpenIdConnectConstants.GrantTypes.AuthorizationCode)
                .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken));

            // We serialize the client_id so we can monitor for usage patterns of a given app, and also to allow for app-based token revokes.
            identity.AddClaim(
                new Claim("client_id", request.ClientId)
                .SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken));



            RegisteredApplication ra = await(from entity in _mockifyContext.Applications
                                             where entity.ClientId == request.ClientId
                                             select entity).SingleOrDefaultAsync(cancellationToken);

            if (ra == null)
            {
                return(View("Error", new AuthorizeErrorViewModel {
                    Error = OpenIdConnectConstants.Errors.InvalidClient,
                    ErrorDescription = "Details concerning the calling client " +
                                       "application cannot be found in the database"
                }));
            }

            AuthenticationTicket ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme);

            List <string> scopesToAdd = new List <string>()
            {
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.OfflineAccess,
                SpotifyScope.Public.Name,
            };

            if (!String.IsNullOrWhiteSpace(request.Scope))
            {
                foreach (string scope in request.Scope.Split(','))
                {
                    if (SpotifyScope.IdMap.ContainsKey(scope) && !scopesToAdd.Contains(scope))
                    {
                        scopesToAdd.Add(scope);
                    }
                }
            }
            ticket.SetScopes(scopesToAdd);
            ticket.SetResources("resource_server"); // ?? what is this
            Microsoft.AspNetCore.Mvc.SignInResult sr = SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
            return(sr);
        }
    public async Task <IActionResult> ExchangeAsync(OpenIdConnectRequest request)
    {
        // Reject the token request if client_id or client_secret is missing.

        /* if (string.IsNullOrEmpty(request.ClientId) || string.IsNullOrEmpty(request.ClientSecret))
         * {
         *  return BadRequest(new OpenIdConnectResponse
         *  {
         *      Error = OpenIdConnectConstants.Errors.InvalidRequest,
         *      ErrorDescription = "Missing credentials: ensure that your credentials were correctly " +
         *                         "flowed in the request body or in the authorization header"
         *  });
         * } */

        // Retrieve the application details from the database.

        /* var application = await _applicationManager.FindByClientIdAsync(request.ClientId, HttpContext.RequestAborted);
         *
         * if (application == null)
         * {
         *  return BadRequest(new OpenIdConnectResponse
         *  {
         *      Error = OpenIdConnectConstants.Errors.InvalidClient,
         *      ErrorDescription = "The credentials is invalid."
         *  });
         * } */

        if (request.IsPasswordGrantType())
        {
            /* if (!string.Equals(application.Type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.Ordinal))
             * {
             *  return BadRequest(new OpenIdConnectResponse
             *  {
             *      Error = OpenIdConnectConstants.Errors.InvalidClient,
             *      ErrorDescription = "Only confidential clients are allowed to use password grant type."
             *  });
             * } */
            var user = _ctx.Users
                       .Where(x => x.Email.Equals(request.Username))
                       .Where(x => x.ProviderName.Equals("EMAIL"))
                       .FirstOrDefault();
            //var user = await _userManager.FindByEmailAsync(request.Username);

            if (user == null)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid."
                }));
            }
            var canSignIn = await _signInManager.CanSignInAsync(user);

            // Ensure the user is allowed to sign in.
            if (!canSignIn)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The specified user is not allowed to sign in."
                }));
            }

            // Reject the token request if two-factor authentication has been enabled by the user.
            if (_userManager.SupportsUserTwoFactor && await _userManager.GetTwoFactorEnabledAsync(user))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The specified user is not allowed to sign in."
                }));
            }

            // Ensure the user is not already locked out.
            if (_userManager.SupportsUserLockout && await _userManager.IsLockedOutAsync(user))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid."
                }));
            }

            // Ensure the password is valid.
            if (!await _userManager.CheckPasswordAsync(user, request.Password))
            {
                if (_userManager.SupportsUserLockout)
                {
                    await _userManager.AccessFailedAsync(user);
                }

                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The username/password couple is invalid."
                }));
            }

            if (_userManager.SupportsUserLockout)
            {
                await _userManager.ResetAccessFailedCountAsync(user);
            }

            var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);

            identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                              user.Id,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Email,
                              user.Email,
                              OpenIdConnectConstants.Destinations.AccessToken);
            if (user.FirstName != null)
            {
                identity.AddClaim(OpenIdConnectConstants.Claims.GivenName,
                                  user.FirstName,
                                  OpenIdConnectConstants.Destinations.AccessToken);
            }
            if (user.LastName != null)
            {
                identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName,
                                  user.LastName,
                                  OpenIdConnectConstants.Destinations.AccessToken);
            }

            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                OpenIdConnectServerDefaults.AuthenticationScheme);

            ticket.SetScopes(
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.OfflineAccess,
                OpenIdConnectConstants.Scopes.Profile,
                OpenIdConnectConstants.Scopes.Email);



            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }

        if (request.IsAuthorizationCodeGrantType())
        {
            // Retrieve the claims principal stored in the authorization code.
            var info = await HttpContext.AuthenticateAsync(
                OpenIdConnectServerDefaults.AuthenticationScheme);

            // Retrieve the user profile corresponding to the authorization code.
            // Note: if you want to automatically invalidate the authorization code
            // when the user password/roles change, use the following line instead:
            //var user = await _signInManager.ValidateSecurityStampAsync(info.Principal);
            var user = await _userManager.GetUserAsync(info.Principal);

            if (user == null)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The authorization code is no longer valid."
                }));
            }

            // Ensure the user is still allowed to sign in.
            if (!await _signInManager.CanSignInAsync(user))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The user is no longer allowed to sign in."
                }));
            }

            // Create a new authentication ticket, but reuse the properties stored
            // in the authorization code, including the scopes originally granted.
            var ticket = await CreateTicketAsync(request, user, info.Properties);

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }

        if (request.IsRefreshTokenGrantType())
        {
            // Retrieve the claims principal stored in the refresh token.
            var info = await HttpContext.AuthenticateAsync(
                OpenIdConnectServerDefaults.AuthenticationScheme);

            // Retrieve the user profile corresponding to the refresh token.
            // Note: if you want to automatically invalidate the refresh token
            // when the user password/roles change, use the following line instead:
            var user = await _signInManager.ValidateSecurityStampAsync(info.Principal);

            //var user = await _userManager.GetUserAsync(info.Principal);

            if (user == null)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The refresh token is no longer valid."
                }));
            }

            // Ensure the user is still allowed to sign in.
            if (!await _signInManager.CanSignInAsync(user))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidGrant,
                    ErrorDescription = "The user is no longer allowed to sign in."
                }));
            }

            // Create a new authentication ticket, but reuse the properties stored
            // in the refresh token, including the scopes originally granted.
            var ticket = await CreateTicketAsync(request, user, info.Properties);

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }

        if (request.GrantType == "urn:ietf:params:oauth:grant-type:google_identity_token")
        {
            // Reject the request if the "assertion" parameter is missing.
            if (string.IsNullOrEmpty(request.Assertion))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = "The mandatory 'assertion' parameter was missing."
                }));
            }


            // Create a new ClaimsIdentity containing the claims that
            // will be used to create an id_token and/or an access token.
            var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
            Console.WriteLine(identity.ToString());
            Console.WriteLine(request.Code);

            var googleDetails = await GetGoogleDetailsAsync(request.Assertion);

            if (googleDetails != null)
            {
                // save
                //check to see if the ProviderId is already listed for this user
                var repeatUser = _ctx.Users
                                 .Where(x => x.ProviderId.Equals(googleDetails.ProviderUserId))
                                 .FirstOrDefault();

                //this signed in google user is not a repeat user and hasn't been saved yet
                if (repeatUser == null)
                {
                    var result = await _userManager.CreateAsync(
                        new ApplicationUser()
                    {
                        Email        = googleDetails.Email,
                        FirstName    = googleDetails.FirstName,
                        UserName     = $"{googleDetails.Email.Split('@')[0]}_Google",
                        FullName     = googleDetails.Name,
                        LastName     = googleDetails.LastName,
                        ProviderId   = googleDetails.ProviderUserId,
                        ProviderName = "GOOGLE",
                        PictureUrl   = "https://cdn.iconscout.com/public/images/icon/premium/png-512/gamer-games-video-casino-372bcf114ef0140a-512x512.png"
                    });

                    if (!result.Succeeded)
                    {
                        AddErrors(result);
                        return(BadRequest(result));
                    }
                    else
                    {
                        _logger.LogInformation("Social User created a new account without password.");

                        //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                        //var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
                        //await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);

                        //await _signInManager.SignInAsync(user, isPersistent: false);
                        //_logger.LogInformation("User created a new account with password.");
                        //return Ok(result);
                        //return RedirectToLocal(returnUrl);
                    }
                }
            }


            // Manually validate the identity token issued by Google,
            // including the issuer, the signature and the audience.
            // Then, copy the claims you need to the "identity" instance.
            identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                              googleDetails.ProviderUserId,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Name, googleDetails.Name,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Email,
                              googleDetails.Email,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.GivenName,
                              googleDetails.FirstName,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName,
                              googleDetails.LastName,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Locale,
                              googleDetails.Locale,
                              OpenIdConnectConstants.Destinations.AccessToken);

            // Create a new authentication ticket holding the user identity.


            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                OpenIdConnectServerDefaults.AuthenticationScheme);

            // Then, copy the claims you need to the "identity" instance.

            ticket.SetScopes(
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.OfflineAccess,
                OpenIdConnectConstants.Scopes.Profile,
                OpenIdConnectConstants.Scopes.Email);

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }

        if (request.GrantType == "urn:ietf:params:oauth:grant-type:facebook_access_token")
        {
            // Reject the request if the "assertion" parameter is missing.
            if (string.IsNullOrEmpty(request.Assertion))
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = "The mandatory 'assertion' parameter was missing."
                }));
            }

            // Create a new ClaimsIdentity containing the claims that
            // will be used to create an id_token and/or an access token.
            var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
            Console.WriteLine(identity.ToString());
            Console.WriteLine(request.Code);

            var fbDetails = await GetFacebookDetailsAsync(request.Assertion);

            if (fbDetails != null)
            {
                // save
                //check to see if the ProviderId is already listed for this user
                var repeatUser = _ctx.Users
                                 .Where(x => x.ProviderId.Equals(fbDetails.ProviderUserId))
                                 .FirstOrDefault();
                // save
                if (repeatUser == null)
                {
                    var result = await _userManager.CreateAsync(
                        new ApplicationUser()
                    {
                        Email        = fbDetails.Email,
                        UserName     = $"{fbDetails.Email.Split('@')[0]}_Facebook",
                        FirstName    = fbDetails.FirstName,
                        FullName     = fbDetails.Name,
                        LastName     = fbDetails.LastName,
                        ProviderId   = fbDetails.ProviderUserId,
                        ProviderName = "FACEBOOK",
                        PictureUrl   = "https://cdn.iconscout.com/public/images/icon/premium/png-512/gamer-games-video-casino-372bcf114ef0140a-512x512.png"
                    });

                    if (!result.Succeeded)
                    {
                        AddErrors(result);
                        return(BadRequest(result));
                    }
                    else
                    {
                        _logger.LogInformation("Social User created a new account without password.");

                        //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                        //var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
                        //await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);

                        //await _signInManager.SignInAsync(user, isPersistent: false);
                        //_logger.LogInformation("User created a new account with password.");
                        //return Ok(result);
                        //return RedirectToLocal(returnUrl);
                    }
                }
            }

            // Manually validate the identity token issued by Google,
            // including the issuer, the signature and the audience.
            // Then, copy the claims you need to the "identity" instance.
            identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                              fbDetails.ProviderUserId,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Name, fbDetails.Name,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Email,
                              fbDetails.Email,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.GivenName,
                              fbDetails.FirstName,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.FamilyName,
                              fbDetails.LastName,
                              OpenIdConnectConstants.Destinations.AccessToken);
            identity.AddClaim(OpenIdConnectConstants.Claims.Locale,
                              fbDetails.Locale,
                              OpenIdConnectConstants.Destinations.AccessToken);

            // Create a new authentication ticket holding the user identity.


            var ticket = new AuthenticationTicket(
                new ClaimsPrincipal(identity),
                new AuthenticationProperties(),
                OpenIdConnectServerDefaults.AuthenticationScheme);

            // Then, copy the claims you need to the "identity" instance.

            ticket.SetScopes(
                OpenIdConnectConstants.Scopes.OpenId,
                OpenIdConnectConstants.Scopes.OfflineAccess,
                OpenIdConnectConstants.Scopes.Profile,
                OpenIdConnectConstants.Scopes.Email);

            return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
        }

        return(BadRequest(new OpenIdConnectResponse
        {
            Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
            ErrorDescription = "The specified grant type is not supported."
        }));
    }
예제 #17
0
        public async Task <IActionResult> Accept(CancellationToken cancellationToken)
        {
            var response = HttpContext.GetOpenIdConnectResponse();

            if (response != null)
            {
                return(BadRequest(response));
            }

            var request = HttpContext.GetOpenIdConnectRequest();

            if (request == null)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.ServerError,
                    ErrorDescription = "Ha ocurrido un error interno."
                }));
            }

            Int32.TryParse(request.GetParameter("authuser").ToString(), out int authuser);
            var companyCode = request.GetParameter("company_code").ToString();
            var user        = User.Identities.ElementAtOrDefault(authuser);

            if (user == null)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.UnauthorizedClient,
                    ErrorDescription = "No se encontro sesión del usuario."
                }));
            }

            if (!user.IsAuthenticated)
            {
                return(Unauthorized());
            }

            try
            {
                var    usuarioId = user.FindFirst(ClaimTypes.NameIdentifier).Value;
                var    empresaId = await(companyCode.Length == 0 ? _repository.GetEmpresaIdAsync(usuarioId) : _repository.GetEmpresaIdAsync(usuarioId, companyCode));
                string rol       = await _repository.GetRolAsync(usuarioId);

                var usuario = await _repository.GetUsuarioPorIdAsync(usuarioId);

                var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme,
                                                  OpenIdConnectConstants.Claims.Name,
                                                  OpenIdConnectConstants.Claims.Role);

                identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "[unique id]");

                identity.AddClaim("UsuarioId", usuarioId,
                                  OpenIdConnectConstants.Destinations.AccessToken,
                                  OpenIdConnectConstants.Destinations.IdentityToken);

                identity.AddClaim(OpenIdConnectConstants.Claims.Audience, "sigecoservices",
                                  OpenIdConnectConstants.Destinations.AccessToken,
                                  OpenIdConnectConstants.Destinations.IdentityToken);

                identity.AddClaim(ClaimTypes.Name, user.FindFirst(ClaimTypes.Name).Value,
                                  OpenIdConnectConstants.Destinations.AccessToken,
                                  OpenIdConnectConstants.Destinations.IdentityToken);

                identity.AddClaim(ClaimTypes.Role, rol,
                                  OpenIdConnectConstants.Destinations.AccessToken,
                                  OpenIdConnectConstants.Destinations.IdentityToken);

                identity.AddClaim("EmpresaId", empresaId.ToString(),
                                  OpenIdConnectConstants.Destinations.AccessToken,
                                  OpenIdConnectConstants.Destinations.IdentityToken);

                identity.AddClaim("ClienteId", request.ClientId.ToString(),
                                  OpenIdConnectConstants.Destinations.AccessToken,
                                  OpenIdConnectConstants.Destinations.IdentityToken);

                var props = new AuthenticationProperties(new Dictionary <string, string>
                {
                    { "client_id", request.ClientId },
                    { "authuser", authuser.ToString() },
                    { "company_code", companyCode },
                });

                var ticket = new AuthenticationTicket(
                    new ClaimsPrincipal(identity),
                    props,
                    OpenIdConnectServerDefaults.AuthenticationScheme);

                ticket.SetScopes(new[]
                {
                    /* openid: */ OpenIdConnectConstants.Scopes.OpenId,
                    /* email: */ OpenIdConnectConstants.Scopes.Email,
                    /* profile: */ OpenIdConnectConstants.Scopes.Profile
                }.Intersect(request.GetScopes()));

                //Otorgamos acceso a aplicación
                var aplicacion = await _repository.GetAplicacionClienteAsync(request.ClientId, cancellationToken);

                if (aplicacion.EsTercero)
                {
                    await _repository.AgregarUsuarioAplicacionAsync(usuarioId, request.ClientId);
                }
                //

                return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme));
            }
            catch (AuthDomainException ex)
            {
                return(BadRequest(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = ex.Message
                }));
            }
        }