public async Task<ConsentInteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, UserConsent consent = null)
        {
            if (request == null) throw new ArgumentNullException("request");

            if (request.PromptMode != null && 
                request.PromptMode != Constants.PromptModes.None &&
                request.PromptMode != Constants.PromptModes.Consent)
            {
                throw new ArgumentException("Invalid PromptMode");
            }

            var consentRequired = await _consent.RequiresConsentAsync(request.Client, request.Subject, request.RequestedScopes);

            if (consentRequired && request.PromptMode == Constants.PromptModes.None)
            {
                Logger.Info("Prompt=none requested, but consent is required.");

                return new ConsentInteractionResponse
                {
                    Error = new AuthorizeError
                    {
                        ErrorType = ErrorTypes.Client,
                        Error = Constants.AuthorizeErrors.InteractionRequired,
                        ResponseMode = request.ResponseMode,
                        ErrorUri = request.RedirectUri,
                        State = request.State
                    }
                };
            }

            if (request.PromptMode == Constants.PromptModes.Consent || consentRequired)
            {
                var response = new ConsentInteractionResponse();

                // did user provide consent
                if (consent == null)
                {
                    // user was not yet shown conset screen
                    response.IsConsent = true;
                }
                else
                {
                    request.WasConsentShown = true;

                    // user was shown consent -- did they say yes or no
                    if (consent.WasConsentGranted == false)
                    {
                        // no need to show consent screen again
                        // build access denied error to return to client
                        response.Error = new AuthorizeError { 
                            ErrorType = ErrorTypes.Client,
                            Error = Constants.AuthorizeErrors.AccessDenied,
                            ResponseMode = request.ResponseMode,
                            ErrorUri = request.RedirectUri, 
                            State = request.State
                        };
                    }
                    else
                    {
                        // they said yes, set scopes they chose
                        request.ValidatedScopes.SetConsentedScopes(consent.ScopedConsented);

                        if (!request.ValidatedScopes.GrantedScopes.Any())
                        {
                            // they said yes, but didn't pick any scopes
                            // show consent again and provide error message
                            response.IsConsent = true;
                            response.ConsentError = _localizationService.GetMessage(MessageIds.MustSelectAtLeastOnePermission);
                        }
                        else if (request.Client.AllowRememberConsent)
                        {
                            // remember consent
                            var scopes = Enumerable.Empty<string>();
                            if (consent.RememberConsent)
                            {
                                // remember what user actually selected
                                scopes = request.ValidatedScopes.GrantedScopes.Select(x => x.Name);
                            }
                            
                            await _consent.UpdateConsentAsync(request.Client, request.Subject, scopes);
                        }
                    }
                }
                
                return response;
            }

            return new ConsentInteractionResponse();
        }
 public Task<IHttpActionResult> PostConsent(UserConsent model)
 {
     Logger.Info("Resuming from consent, restarting validation");
     return ProcessRequestAsync(Request.RequestUri.ParseQueryString(), model ?? new UserConsent());
 }
        private IHttpActionResult CreateConsentResult(
            ValidatedAuthorizeRequest validatedRequest,
            UserConsent consent,
            NameValueCollection requestParameters,
            string errorMessage)
        {
            string loginWithDifferentAccountUrl = null;
            if (validatedRequest.HasIdpAcrValue() == false)
            {
                loginWithDifferentAccountUrl = Url.Route(Constants.RouteNames.Oidc.SwitchUser, null)
                    .AddQueryString(requestParameters.ToQueryString());
            }
            
            var env = Request.GetOwinEnvironment();
            var consentModel = new ConsentViewModel
            {
                RequestId = env.GetRequestId(),
                SiteName = _options.SiteName,
                SiteUrl = env.GetIdentityServerBaseUrl(),
                ErrorMessage = errorMessage,
                CurrentUser = env.GetCurrentUserDisplayName(),
                LogoutUrl = env.GetIdentityServerLogoutUrl(),
                ClientName = validatedRequest.Client.ClientName,
                ClientUrl = validatedRequest.Client.ClientUri,
                ClientLogoUrl = validatedRequest.Client.LogoUri,
                IdentityScopes = validatedRequest.GetIdentityScopes(this._localizationService),
                ResourceScopes = validatedRequest.GetResourceScopes(this._localizationService),
                AllowRememberConsent = validatedRequest.Client.AllowRememberConsent,
                RememberConsent = consent == null || consent.RememberConsent,
                LoginWithDifferentAccountUrl = loginWithDifferentAccountUrl,
                ConsentUrl = Url.Route(Constants.RouteNames.Oidc.Consent, null).AddQueryString(requestParameters.ToQueryString()),
                AntiForgery = _antiForgeryToken.GetAntiForgeryToken()
            };

            return new ConsentActionResult(_viewService, consentModel, validatedRequest);
        }
        private async Task<IHttpActionResult> ProcessRequestAsync(NameValueCollection parameters, UserConsent consent = null)
        {
            // validate request
            var result = await _validator.ValidateAsync(parameters, User as ClaimsPrincipal);
            
            if (result.IsError)
            {
                return await this.AuthorizeErrorAsync(
                    result.ErrorType,
                    result.Error,
                    result.ValidatedRequest);
            }

            var request = result.ValidatedRequest;
            var loginInteraction = await _interactionGenerator.ProcessLoginAsync(request, User as ClaimsPrincipal);

            if (loginInteraction.IsError)
            {
                return await this.AuthorizeErrorAsync(
                    loginInteraction.Error.ErrorType,
                    loginInteraction.Error.Error,
                    request);
            }
            if (loginInteraction.IsLogin)
            {
                return this.RedirectToLogin(loginInteraction.SignInMessage, request.Raw);
            }

            // user must be authenticated at this point
            if (!User.Identity.IsAuthenticated)
            {
                throw new InvalidOperationException("User is not authenticated");
            }

            request.Subject = User as ClaimsPrincipal;

            // now that client configuration is loaded, we can do further validation
            loginInteraction = await _interactionGenerator.ProcessClientLoginAsync(request);
            if (loginInteraction.IsLogin)
            {
                return this.RedirectToLogin(loginInteraction.SignInMessage, request.Raw);
            }

            var consentInteraction = await _interactionGenerator.ProcessConsentAsync(request, consent);

            if (consentInteraction.IsError)
            {
                return await this.AuthorizeErrorAsync(
                    consentInteraction.Error.ErrorType,
                    consentInteraction.Error.Error,
                    request);
            }

            if (consentInteraction.IsConsent)
            {
                Logger.Info("Showing consent screen");
                return CreateConsentResult(request, consent, request.Raw, consentInteraction.ConsentError);
            }

            return await CreateAuthorizeResponseAsync(request);
        }
 public async Task ProcessConsentAsync_AllowConsentSelected_SavesConsent()
 {
     RequiresConsent(true);
     var client = new Client { AllowRememberConsent = true };
     var user = new ClaimsPrincipal();
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         ValidatedScopes = new ScopeValidator(new InMemoryScopeStore(GetScopes())),
         Client = client,
         Subject = user
     };
     await request.ValidatedScopes.AreScopesValidAsync(new string[] { "read", "write" });
     var consent = new UserConsent
     {
         Button = "yes",
         RememberConsent = true,
         Scopes = new string[] { "read" }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     AssertUpdateConsentCalled(client, user, "read");
 }
 public async Task ProcessConsentAsync_PromptModeConsent_ConsentGranted_ScopesSelected_ReturnsConsentResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         ValidatedScopes = new ScopeValidator(new InMemoryScopeStore(GetScopes())),
         Client = new Client {
             AllowRememberConsent = false
         }
     };
     await request.ValidatedScopes.AreScopesValidAsync(new string[] { "read", "write" });
     var consent = new UserConsent
     {
         Button = "yes",
         RememberConsent = false,
         Scopes = new string[] { "read" }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     request.ValidatedScopes.GrantedScopes.Count.Should().Be(1);
     "read".Should().Be(request.ValidatedScopes.GrantedScopes.First().Name);
     request.WasConsentShown.Should().BeTrue();
     result.IsConsent.Should().BeFalse();
     AssertUpdateConsentNotCalled();
 }
 public void ProcessConsentAsync_NoPromptMode_ConsentServiceRequiresConsent_ConsentGranted_NoScopesSelected_ReturnsConsentResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         ValidatedScopes = new ScopeValidator(null),
         Client = new Client { }
     };
     var consent = new UserConsent
     {
         Button = "yes",
         RememberConsent = false,
         Scopes = new string[] {  }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     request.WasConsentShown.Should().BeTrue();
     result.IsConsent.Should().BeTrue();
     result.ConsentError.Should().Be(Messages.MustSelectAtLeastOnePermission);
     AssertUpdateConsentNotCalled();
 }
 public void ProcessConsentAsync_NoPromptMode_ConsentServiceRequiresConsent_ConsentNotGranted_ReturnsErrorResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
     };
     var consent = new UserConsent
     {
         Button = "no",
         RememberConsent = false,
         Scopes = new string[] { "read", "write" }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     request.WasConsentShown.Should().BeTrue();
     result.IsError.Should().BeTrue();
     result.Error.ErrorType.Should().Be(ErrorTypes.Client);
     result.Error.Error.Should().Be(Constants.AuthorizeErrors.AccessDenied);
     AssertErrorReturnsRequestValues(result.Error, request);
     AssertUpdateConsentNotCalled();
 }