public async Task Authorize()

in src/OrchardCore.Modules/OrchardCore.OpenId/Controllers/AccessController.cs [51:192]


        public async Task<IActionResult> Authorize()
        {
            var response = HttpContext.GetOpenIddictServerResponse();
            if (response != null)
            {
                return View("Error", new ErrorViewModel
                {
                    Error = response.Error,
                    ErrorDescription = response.ErrorDescription
                });
            }

            var request = HttpContext.GetOpenIddictServerRequest();
            if (request == null)
            {
                return NotFound();
            }

            // Retrieve the claims stored in the authentication cookie.
            // If they can't be extracted, redirect the user to the login page.
            var result = await HttpContext.AuthenticateAsync();
            if (result == null || !result.Succeeded || request.HasPrompt(Prompts.Login))
            {
                return RedirectToLoginPage(request);
            }

            // 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))
            {
                return RedirectToLoginPage(request);
            }

            var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
                throw new InvalidOperationException("The application details cannot be found.");

            var authorizations = await _authorizationManager.FindAsync(
                subject: result.Principal.GetUserIdentifier(),
                client : await _applicationManager.GetIdAsync(application),
                status : Statuses.Valid,
                type   : AuthorizationTypes.Permanent,
                scopes : request.GetScopes()).ToListAsync();

            switch (await _applicationManager.GetConsentTypeAsync(application))
            {
                case ConsentTypes.External when !authorizations.Any():
                    return Forbid(new AuthenticationProperties(new Dictionary<string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            S["The logged in user is not allowed to access this client application."]
                    }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

                case ConsentTypes.Implicit:
                case ConsentTypes.External when authorizations.Any():
                case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent):
                    var identity = new ClaimsIdentity(result.Principal.Claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
                    var principal = new ClaimsPrincipal(identity);

                    identity.AddClaim(OpenIdConstants.Claims.EntityType, OpenIdConstants.EntityTypes.User,
                        Destinations.AccessToken, Destinations.IdentityToken);

                    // Note: while ASP.NET Core Identity uses the legacy WS-Federation claims (exposed by the ClaimTypes class),
                    // OpenIddict uses the newer JWT claims defined by the OpenID Connect specification. To ensure the mandatory
                    // subject claim is correctly populated (and avoid an InvalidOperationException), it's manually added here.
                    if (string.IsNullOrEmpty(result.Principal.FindFirst(Claims.Subject)?.Value))
                    {
                        identity.AddClaim(new Claim(Claims.Subject, result.Principal.GetUserIdentifier()));
                    }

                    principal.SetScopes(request.GetScopes());
                    principal.SetResources(await GetResourcesAsync(request.GetScopes()));

                    // 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  : principal.GetUserIdentifier(),
                            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);

                case ConsentTypes.Explicit when request.HasPrompt(Prompts.None):
                    return Forbid(new AuthenticationProperties(new Dictionary<string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            S["Interactive user consent is required."]
                    }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

                default:
                    return View(new AuthorizeViewModel
                    {
                        ApplicationName = await _applicationManager.GetLocalizedDisplayNameAsync(application),
                        RequestId = request.RequestId,
                        Scope = request.Scope
                    });
            }

            IActionResult RedirectToLoginPage(OpenIddictRequest request)
            {
                // 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(new AuthenticationProperties(new Dictionary<string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
                        [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
                            S["The user is not logged in."]
                    }), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
                }

                string GetRedirectUrl()
                {
                    // Override the prompt parameter to prevent infinite authentication/authorization loops.
                    var parameters = Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
                    parameters[Parameters.Prompt] = "continue";

                    return Request.PathBase + Request.Path + QueryString.Create(parameters);
                }

                return Challenge(new AuthenticationProperties
                {
                    RedirectUri = GetRedirectUrl()
                });
            }
        }