コード例 #1
0
        private async Task <ClaimsPrincipal> CreateApplicationPrinicpalAsync(OpenIddictRequest request, object application)
        {
            var identity = new ClaimsIdentity(
                TokenValidationParameters.DefaultAuthenticationType,
                Claims.Name,
                Claims.Role);

            var principal = new ClaimsPrincipal(identity);

            var clientId   = request.ClientId;
            var clientName = await applicationManager.GetDisplayNameAsync(application);

            if (clientId != null)
            {
                identity.AddClaim(Claims.Subject, clientId,
                                  Destinations.AccessToken, Destinations.IdentityToken);
            }

            if (clientName != null)
            {
                identity.AddClaim(Claims.Name, clientName,
                                  Destinations.AccessToken, Destinations.IdentityToken);
            }

            var properties = await applicationManager.GetPropertiesAsync(application);

            foreach (var claim in properties.Claims())
            {
                identity.AddClaim(claim);
            }

            await EnrichPrincipalAsync(request, principal, true);

            return(principal);
        }
コード例 #2
0
    public async Task <ClaimsPrincipal> Handle(OpenIddictRequest request)
    {
        if (!request.IsClientCredentialsGrantType())
        {
            throw new NotImplementedException("The specified grant type is not implemented");
        }

        var application = await _applicationManager.FindByClientIdAsync(request.ClientId !) ??
                          throw new NotFoundException <string?>("Admin API Client", request.ClientId);

        if (!await _applicationManager.ValidateClientSecretAsync(application, request.ClientSecret !))
        {
            throw new AuthenticationException("Invalid Admin API Client key and secret");
        }

        var requestedScopes = request.GetScopes();
        var appScopes       = (await _applicationManager.GetPermissionsAsync(application))
                              .Where(p => p.StartsWith(OpenIddictConstants.Permissions.Prefixes.Scope))
                              .Select(p => p.Substring(OpenIddictConstants.Permissions.Prefixes.Scope.Length))
                              .ToList();

        var missingScopes = requestedScopes.Where(s => !appScopes.Contains(s)).ToList();

        if (missingScopes.Any())
        {
            throw new AuthenticationException($"Client is not allowed access to requested scope(s): {string.Join(", " , missingScopes)}");
        }

        var displayName = await _applicationManager.GetDisplayNameAsync(application);

        var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);

        identity.AddClaim(OpenIddictConstants.Claims.Subject, request.ClientId !, OpenIddictConstants.Destinations.AccessToken);
        identity.AddClaim(OpenIddictConstants.Claims.Name, displayName !, OpenIddictConstants.Destinations.AccessToken);

        var principal = new ClaimsPrincipal(identity);

        principal.SetScopes(requestedScopes);

        return(principal);
    }
コード例 #3
0
        public async Task <IActionResult> Authorize()
        {
            var request = HttpContext.GetOpenIddictServerRequest() ??
                          throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");

            // Retrieve the user principal stored in the authentication cookie.
            // If it can't be extracted, redirect the user to the login page.
            var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);

            if (result == null || !result.Succeeded)
            {
                // If the client application requested promptless authentication,
                // return an error indicating that the user is not logged in.
                if (request.HasPrompt(Prompts.None))
                {
                    return(Forbid(
                               authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                               properties: new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
                    })));
                }

                return(Challenge(
                           authenticationSchemes: IdentityConstants.ApplicationScheme,
                           properties: new AuthenticationProperties
                {
                    RedirectUri = Request.PathBase + Request.Path + QueryString.Create(
                        Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList())
                }));
            }

            // If prompt=login was specified by the client application,
            // immediately return the user agent to the login page.
            if (request.HasPrompt(Prompts.Login))
            {
                // To avoid endless login -> authorization redirects, the prompt=login flag
                // is removed from the authorization request payload before redirecting the user.
                var prompt = string.Join(" ", request.GetPrompts().Remove(Prompts.Login));

                var parameters = Request.HasFormContentType ?
                                 Request.Form.Where(parameter => parameter.Key != Parameters.Prompt).ToList() :
                                 Request.Query.Where(parameter => parameter.Key != Parameters.Prompt).ToList();

                parameters.Add(KeyValuePair.Create(Parameters.Prompt, new StringValues(prompt)));

                return(Challenge(
                           authenticationSchemes: IdentityConstants.ApplicationScheme,
                           properties: new AuthenticationProperties
                {
                    RedirectUri = Request.PathBase + Request.Path + QueryString.Create(parameters)
                }));
            }

            // If a max_age parameter was provided, ensure that the cookie is not too old.
            // If it's too old, automatically redirect the user agent to the login page.
            if (request.MaxAge != null && result.Properties?.IssuedUtc != null &&
                DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))
            {
                if (request.HasPrompt(Prompts.None))
                {
                    return(Forbid(
                               authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                               properties: new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
                    })));
                }

                return(Challenge(
                           authenticationSchemes: IdentityConstants.ApplicationScheme,
                           properties: new AuthenticationProperties
                {
                    RedirectUri = Request.PathBase + Request.Path + QueryString.Create(
                        Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList())
                }));
            }

            // Retrieve the profile of the logged in user.
            var user = await _userManager.GetUserAsync(result.Principal) ??
                       throw new InvalidOperationException("The user details cannot be retrieved.");

            // Retrieve the application details from the database.
            var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
                              throw new InvalidOperationException("Details concerning the calling client application cannot be found.");

            // Retrieve the permanent authorizations associated with the user and the calling client application.
            var authorizations = await _authorizationManager.FindAsync(
                subject : await _userManager.GetUserIdAsync(user),
                client : await _applicationManager.GetIdAsync(application),
                status : Statuses.Valid,
                type : AuthorizationTypes.Permanent,
                scopes : request.GetScopes()).ToListAsync();

            switch (await _applicationManager.GetConsentTypeAsync(application))
            {
            // If the consent is external (e.g when authorizations are granted by a sysadmin),
            // immediately return an error if no authorization can be found in the database.
            case ConsentTypes.External when !authorizations.Any():
                return(Forbid(
                           authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                           properties: new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
                    [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                        "The logged in user is not allowed to access this client application."
                })));

            // If the consent is implicit or if an authorization was found,
            // return an authorization response without displaying the consent form.
            case ConsentTypes.Implicit:
            case ConsentTypes.External when authorizations.Any():
            case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent):
                var principal = await _signInManager.CreateUserPrincipalAsync(user);

                // Note: in this sample, the granted scopes match the requested scope
                // but you may want to allow the user to uncheck specific scopes.
                // For that, simply restrict the list of scopes before calling SetScopes.
                principal.SetScopes(request.GetScopes());
                principal.SetResources(await _scopeManager.ListResourcesAsync(principal.GetScopes()).ToListAsync());

                // Automatically create a permanent authorization to avoid requiring explicit consent
                // for future authorization or token requests containing the same scopes.
                var authorization = authorizations.LastOrDefault();
                if (authorization == null)
                {
                    authorization = await _authorizationManager.CreateAsync(
                        principal : principal,
                        subject : await _userManager.GetUserIdAsync(user),
                        client : await _applicationManager.GetIdAsync(application),
                        type : AuthorizationTypes.Permanent,
                        scopes : principal.GetScopes());
                }

                principal.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization));

                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));

            // At this point, no authorization was found in the database and an error must be returned
            // if the client application specified prompt=none in the authorization request.
            case ConsentTypes.Explicit   when request.HasPrompt(Prompts.None):
            case ConsentTypes.Systematic when request.HasPrompt(Prompts.None):
                return(Forbid(
                           authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                           properties: new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
                    [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                        "Interactive user consent is required."
                })));

            // In every other case, render the consent form.
            default:
                return(View(new AuthorizeViewModel
                {
                    ApplicationName = await _applicationManager.GetDisplayNameAsync(application),
                    Scope = request.Scope
                }));
            }
        }
コード例 #4
0
        public async Task <ActionResult> Authorize()
        {
            var context = HttpContext.GetOwinContext();
            var request = context.GetOpenIddictServerRequest() ??
                          throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");

            // Retrieve the user principal stored in the authentication cookie.
            // If a max_age parameter was provided, ensure that the cookie is not too old.
            // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page.
            var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie);

            if (result?.Identity == null || (request.MaxAge != null && result.Properties?.IssuedUtc != null &&
                                             DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value)))
            {
                // For applications that want to allow the client to select the external authentication provider
                // that will be used to authenticate the user, the identity_provider parameter can be used for that.
                if (!string.IsNullOrEmpty(request.IdentityProvider))
                {
                    var issuer = request.IdentityProvider switch
                    {
                        "github" => "https://github.com/",

                        _ => null
                    };

                    if (string.IsNullOrEmpty(issuer))
                    {
                        context.Authentication.Challenge(
                            authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
                            properties: new AuthenticationProperties(new Dictionary <string, string>
                        {
                            [OpenIddictServerOwinConstants.Properties.Error]            = Errors.InvalidRequest,
                            [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
                                "The specified identity provider is not valid."
                        }));

                        return(new EmptyResult());
                    }

                    var properties = new AuthenticationProperties(new Dictionary <string, string>
                    {
                        // Note: when only one client is registered in the client options,
                        // setting the issuer property is not required and can be omitted.
                        [OpenIddictClientOwinConstants.Properties.Issuer] = issuer
                    })
                    {
                        // Once the callback is handled, redirect the user agent to the ASP.NET Identity
                        // page responsible for showing the external login confirmation form if necessary.
                        RedirectUri = Url.Action("ExternalLoginCallback", "Account", new
                        {
                            ReturnUrl = Request.RawUrl
                        })
                    };

                    // Ask the OpenIddict client middleware to redirect the user agent to the identity provider.
                    context.Authentication.Challenge(properties, OpenIddictClientOwinDefaults.AuthenticationType);
                    return(new EmptyResult());
                }

                context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie);
                return(new EmptyResult());
            }

            // Retrieve the profile of the logged in user.
            var user = await context.GetUserManager <ApplicationUserManager>().FindByIdAsync(result.Identity.GetUserId()) ??
                       throw new InvalidOperationException("The user details cannot be retrieved.");

            // Retrieve the application details from the database.
            var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
                              throw new InvalidOperationException("Details concerning the calling client application cannot be found.");

            // Retrieve the permanent authorizations associated with the user and the calling client application.
            var authorizations = await _authorizationManager.FindAsync(
                subject : user.Id,
                client : await _applicationManager.GetIdAsync(application),
                status : Statuses.Valid,
                type : AuthorizationTypes.Permanent,
                scopes : request.GetScopes()).ToListAsync();

            switch (await _applicationManager.GetConsentTypeAsync(application))
            {
            // If the consent is external (e.g when authorizations are granted by a sysadmin),
            // immediately return an error if no authorization can be found in the database.
            case ConsentTypes.External when !authorizations.Any():
                context.Authentication.Challenge(
                    authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
                    properties: new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerOwinConstants.Properties.Error]            = Errors.ConsentRequired,
                    [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
                        "The logged in user is not allowed to access this client application."
                }));

                return(new EmptyResult());

            // If the consent is implicit or if an authorization was found,
            // return an authorization response without displaying the consent form.
            case ConsentTypes.Implicit:
            case ConsentTypes.External when authorizations.Any():
            case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent):
                // Create the claims-based identity that will be used by OpenIddict to generate tokens.
                var identity = new ClaimsIdentity(OpenIddictServerOwinDefaults.AuthenticationType)
                               .AddClaim(Claims.Subject, user.Id)
                               .AddClaim(Claims.Email, user.Email)
                               .AddClaim(Claims.Name, user.UserName)
                               .AddClaims(Claims.Role, (await context.Get <ApplicationUserManager>().GetRolesAsync(user.Id)).ToImmutableArray());

                // Note: in this sample, the granted scopes match the requested scope
                // but you may want to allow the user to uncheck specific scopes.
                // For that, simply restrict the list of scopes before calling SetScopes.
                identity.SetScopes(request.GetScopes());
                identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync());

                // Automatically create a permanent authorization to avoid requiring explicit consent
                // for future authorization or token requests containing the same scopes.
                var authorization = authorizations.LastOrDefault();
                if (authorization == null)
                {
                    authorization = await _authorizationManager.CreateAsync(
                        principal : new ClaimsPrincipal(identity),
                        subject : user.Id,
                        client : await _applicationManager.GetIdAsync(application),
                        type : AuthorizationTypes.Permanent,
                        scopes : identity.GetScopes());
                }

                identity.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization));
                identity.SetDestinations(GetDestinations);

                context.Authentication.SignIn(new AuthenticationProperties(), identity);

                return(new EmptyResult());

            // At this point, no authorization was found in the database and an error must be returned
            // if the client application specified prompt=none in the authorization request.
            case ConsentTypes.Explicit   when request.HasPrompt(Prompts.None):
            case ConsentTypes.Systematic when request.HasPrompt(Prompts.None):
                context.Authentication.Challenge(
                    authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
                    properties: new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerOwinConstants.Properties.Error]            = Errors.ConsentRequired,
                    [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
                        "Interactive user consent is required."
                }));

                return(new EmptyResult());

            // In every other case, render the consent form.
            default: return(View(new AuthorizeViewModel
                {
                    ApplicationName = await _applicationManager.GetDisplayNameAsync(application),
                    Scope = request.Scope,

                    // Flow the request parameters so they can be received by the Accept/Reject actions.
                    Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ?
                                 from name in Request.Form.AllKeys
                                 from value in Request.Form.GetValues(name)
                                 select new KeyValuePair <string, string>(name, value) :
                                 from name in Request.QueryString.AllKeys
                                 from value in Request.QueryString.GetValues(name)
                                 select new KeyValuePair <string, string>(name, value)
                }));
            }
        }
コード例 #5
0
        public async Task <IActionResult> Exchange()
        {
            var request = HttpContext.GetOpenIddictServerRequest() ??
                          throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");

            if (request.IsPasswordGrantType())
            {
                var user = await _userManager.FindByNameAsync(request.Username);

                if (user is null)
                {
                    return(Forbid(
                               authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                               properties: new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            "The username/password couple is invalid."
                    })));
                }

                // Validate the username/password parameters and ensure the account is not locked out.
                var result =
                    await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure : true);

                if (!result.Succeeded)
                {
                    return(Forbid(
                               authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                               properties: new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            "The username/password couple is invalid."
                    })));
                }

                var principal = await _signInManager.CreateUserPrincipalAsync(user);

                // Note: in this sample, the granted scopes match the requested scope
                // but you may want to allow the user to uncheck specific scopes.
                // For that, simply restrict the list of scopes before calling SetScopes.
                principal.SetScopes(request.GetScopes());
                principal.SetResources(await _scopeManager.ListResourcesAsync(principal.GetScopes()).ToListAsync());

                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
            }
            else if (request.IsAuthorizationCodeGrantType() || request.IsDeviceCodeGrantType() ||
                     request.IsRefreshTokenGrantType())
            {
                // Retrieve the claims principal stored in the authorization code/device code/refresh token.
                var principal =
                    (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme))
                    .Principal;

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

                if (user is null)
                {
                    return(Forbid(
                               authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                               properties: new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            "The token is no longer valid."
                    })));
                }

                // Ensure the user is still allowed to sign in.
                if (!await _signInManager.CanSignInAsync(user))
                {
                    return(Forbid(
                               authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
                               properties: new AuthenticationProperties(new Dictionary <string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            "The user is no longer allowed to sign in."
                    })));
                }

                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
            }
            else if (request.IsClientCredentialsGrantType())
            {
                // Note: the client credentials are automatically validated by OpenIddict:
                // if client_id or client_secret are invalid, this action won't be invoked.

                var application = await _applicationManager.FindByClientIdAsync(request.ClientId);

                if (application == null)
                {
                    throw new InvalidOperationException("The application details cannot be found in the database.");
                }

                // 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(
                    TokenValidationParameters.DefaultAuthenticationType,
                    Claims.Name, Claims.Role);

                // Use the client_id as the subject identifier.
                identity.AddClaim(Claims.Subject, await _applicationManager.GetClientIdAsync(application),
                                  Destinations.AccessToken, Destinations.IdentityToken);

                identity.AddClaim(Claims.Name, await _applicationManager.GetDisplayNameAsync(application),
                                  Destinations.AccessToken, Destinations.IdentityToken);

                var principal = new ClaimsPrincipal();
                principal.AddIdentity(identity);
                // Note: in this sample, the granted scopes match the requested scope
                // but you may want to allow the user to uncheck specific scopes.
                // For that, simply restrict the list of scopes before calling SetScopes.
                principal.SetScopes(request.GetScopes());
                principal.SetResources(await _scopeManager.ListResourcesAsync(principal.GetScopes()).ToListAsync());
                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                return(SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
            }

            throw new InvalidOperationException("The specified grant type is not supported.");
        }
コード例 #6
0
        public async Task <ActionResult> Authorize()
        {
            var context = HttpContext.GetOwinContext();
            var request = context.GetOpenIddictServerRequest() ??
                          throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");

            // Retrieve the user principal stored in the authentication cookie.
            // If a max_age parameter was provided, ensure that the cookie is not too old.
            // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page.
            var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie);

            if (result?.Identity == null || (request.MaxAge != null && result.Properties?.IssuedUtc != null &&
                                             DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value)))
            {
                context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie);

                return(new EmptyResult());
            }

            // Retrieve the profile of the logged in user.
            var user = await context.GetUserManager <ApplicationUserManager>().FindByIdAsync(result.Identity.GetUserId()) ??
                       throw new InvalidOperationException("The user details cannot be retrieved.");

            // Retrieve the application details from the database.
            var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
                              throw new InvalidOperationException("Details concerning the calling client application cannot be found.");

            // Retrieve the permanent authorizations associated with the user and the calling client application.
            var authorizations = await _authorizationManager.FindAsync(
                subject : user.Id,
                client : await _applicationManager.GetIdAsync(application),
                status : Statuses.Valid,
                type : AuthorizationTypes.Permanent,
                scopes : request.GetScopes()).ToListAsync();

            switch (await _applicationManager.GetConsentTypeAsync(application))
            {
            // If the consent is external (e.g when authorizations are granted by a sysadmin),
            // immediately return an error if no authorization can be found in the database.
            case ConsentTypes.External when !authorizations.Any():
                context.Authentication.Challenge(
                    authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
                    properties: new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerOwinConstants.Properties.Error]            = Errors.ConsentRequired,
                    [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
                        "The logged in user is not allowed to access this client application."
                }));

                return(new EmptyResult());

            // If the consent is implicit or if an authorization was found,
            // return an authorization response without displaying the consent form.
            case ConsentTypes.Implicit:
            case ConsentTypes.External when authorizations.Any():
            case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent):
                var identity = new ClaimsIdentity(OpenIddictServerOwinDefaults.AuthenticationType);

                identity.AddClaims((await context.Get <ApplicationSignInManager>().CreateUserIdentityAsync(user)).Claims);

                identity.AddClaim(new Claim(Claims.Subject, identity.FindFirstValue(ClaimTypes.NameIdentifier)));
                identity.AddClaim(new Claim(Claims.Name, identity.FindFirstValue(ClaimTypes.Name)));

                var principal = new ClaimsPrincipal(identity);

                // Note: in this sample, the granted scopes match the requested scope
                // but you may want to allow the user to uncheck specific scopes.
                // For that, simply restrict the list of scopes before calling SetScopes.
                principal.SetScopes(request.GetScopes());
                principal.SetResources(await _scopeManager.ListResourcesAsync(principal.GetScopes()).ToListAsync());

                // Automatically create a permanent authorization to avoid requiring explicit consent
                // for future authorization or token requests containing the same scopes.
                var authorization = authorizations.LastOrDefault();
                if (authorization == null)
                {
                    authorization = await _authorizationManager.CreateAsync(
                        principal : principal,
                        subject : user.Id,
                        client : await _applicationManager.GetIdAsync(application),
                        type : AuthorizationTypes.Permanent,
                        scopes : principal.GetScopes());
                }

                principal.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization));

                foreach (var claim in principal.Claims)
                {
                    claim.SetDestinations(GetDestinations(claim, principal));
                }

                context.Authentication.SignIn(new AuthenticationProperties(), (ClaimsIdentity)principal.Identity);

                return(new EmptyResult());

            // At this point, no authorization was found in the database and an error must be returned
            // if the client application specified prompt=none in the authorization request.
            case ConsentTypes.Explicit   when request.HasPrompt(Prompts.None):
            case ConsentTypes.Systematic when request.HasPrompt(Prompts.None):
                context.Authentication.Challenge(
                    authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType,
                    properties: new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerOwinConstants.Properties.Error]            = Errors.ConsentRequired,
                    [OpenIddictServerOwinConstants.Properties.ErrorDescription] =
                        "Interactive user consent is required."
                }));

                return(new EmptyResult());

            // In every other case, render the consent form.
            default: return(View(new AuthorizeViewModel
                {
                    ApplicationName = await _applicationManager.GetDisplayNameAsync(application),
                    Scope = request.Scope,

                    // Flow the request parameters so they can be received by the Accept/Reject actions.
                    Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ?
                                 from name in Request.Form.AllKeys
                                 from value in Request.Form.GetValues(name)
                                 select new KeyValuePair <string, string>(name, value) :
                                 from name in Request.QueryString.AllKeys
                                 from value in Request.QueryString.GetValues(name)
                                 select new KeyValuePair <string, string>(name, value)
                }));
            }
        }