private HttpResponseMessage ProcessAuthorizationCodeRequest(ValidatedRequest validatedRequest)
        {
            Tracing.Information("Processing authorization code request");

            var tokenService = new OidcTokenService(
                ServerConfiguration.Global.IssuerUri, 
                ServerConfiguration.Keys.SigningCertificate);

            var response = tokenService.CreateTokenResponse(validatedRequest.Grant, validatedRequest.Client.AccessTokenLifetime);
            Grants.Delete(validatedRequest.Grant.GrantId);

            if (validatedRequest.Grant.Scopes.Contains(OidcConstants.Scopes.OfflineAccess) &&
                validatedRequest.Client.AllowRefreshToken)
            {
                var refreshToken = StoredGrant.CreateRefreshToken(
                    validatedRequest.Grant.ClientId,
                    validatedRequest.Grant.Subject,
                    validatedRequest.Grant.Scopes,
                    validatedRequest.Client.RefreshTokenLifetime);

                Grants.Add(refreshToken);
                response.RefreshToken = refreshToken.GrantId;
            }

            return Request.CreateTokenResponse(response);
        }
        private ActionResult PerformAuthorizationCodeGrant(ValidatedRequest validatedRequest)
        {
            Tracing.Information("Processing authorization code request");

            var grant = StoredGrant.CreateAuthorizationCode(
                validatedRequest.Client.ClientId,
                ClaimsPrincipal.Current.Identity.Name,
                validatedRequest.Scopes,
                validatedRequest.RedirectUri,
                60);

            Grants.Add(grant);

            var tokenString = string.Format("code={0}", grant.GrantId);

            if (!string.IsNullOrWhiteSpace(validatedRequest.State))
            {
                tokenString = string.Format("{0}&state={1}", tokenString, Server.UrlEncode(validatedRequest.State));
            }

            var redirectString = string.Format("{0}?{1}",
                        validatedRequest.RedirectUri,
                        tokenString);

            return Redirect(redirectString);
        }
        private HttpResponseMessage ProcessRefreshTokenRequest(ValidatedRequest validatedRequest)
        {
            Tracing.Information("Processing refresh token request");

            var tokenService = new OidcTokenService(ServerConfiguration.Global.IssuerUri, ServerConfiguration.Keys.SigningCertificate);
            var response = tokenService.CreateTokenResponse(validatedRequest.Grant);

            response.RefreshToken = validatedRequest.Grant.GrantId;
            return Request.CreateTokenResponse(response);
        }
        private ActionResult PerformGrant(ValidatedRequest validatedRequest)
        {
            // implicit grant
            if (validatedRequest.ResponseType.Equals(OAuth2Constants.ResponseTypes.Token, StringComparison.Ordinal))
            {
                return PerformImplicitGrant(validatedRequest);
            }

            // authorization code grant
            if (validatedRequest.ResponseType.Equals(OAuth2Constants.ResponseTypes.Code, StringComparison.Ordinal))
            {
                return PerformAuthorizationCodeGrant(validatedRequest);
            }

            return null;
        }
        protected bool TryValidateRequest(AuthorizeRequest request, 
            out ValidatedRequest validatedRequest, 
            out ActionResult failedResult)
        {
            validatedRequest = null;
            failedResult = null;

            try
            {
                var validator = new AuthorizeRequestValidator(Clients);
                validatedRequest = validator.Validate(request);
                return true;
            }
            catch (AuthorizeRequestValidationException ex)
            {
                failedResult = this.AuthorizeValidationError(ex);
                return false;
            }
        }
        public ValidatedRequest Validate(AuthorizeRequest request)
        {
            var validatedRequest = new ValidatedRequest();

            // validate request model binding
            if (request == null)
            {
                throw new AuthorizeRequestResourceOwnerException("Invalid request parameters.");
            }

            // make sure redirect uri is present
            if (string.IsNullOrWhiteSpace(request.redirect_uri))
            {
                throw new AuthorizeRequestResourceOwnerException("Missing redirect URI");
            }

            // validate client
            if (string.IsNullOrWhiteSpace(request.client_id))
            {
                throw new AuthorizeRequestResourceOwnerException("Missing client identifier");
            }


            var client = Clients.Get(request.client_id);
            
            if (client == null)
            {
                throw new AuthorizeRequestResourceOwnerException("Invalid client: " + request.client_id);
            }

            validatedRequest.Client = client;
            Tracing.InformationFormat("Client: {0} ({1})",
                validatedRequest.Client.Name,
                validatedRequest.Client.ClientId);

            // make sure redirect_uri is a valid uri, and in case of http is over ssl
            Uri redirectUri;
            if (Uri.TryCreate(request.redirect_uri, UriKind.Absolute, out redirectUri))
            {
                if (redirectUri.Scheme == Uri.UriSchemeHttp)
                {
                    throw new AuthorizeRequestClientException(
                        "Redirect URI not over SSL : " + request.redirect_uri,
                        new Uri(request.redirect_uri),
                        OAuth2Constants.Errors.InvalidRequest,
                        string.Empty,
                        validatedRequest.State);
                }

                // make sure redirect uri is registered with client
                if (!validatedRequest.Client.RedirectUris.Contains(request.redirect_uri))
                {
                    throw new AuthorizeRequestResourceOwnerException("Invalid redirect URI: " + request.redirect_uri);
                }

                validatedRequest.RedirectUri = request.redirect_uri;
                Tracing.InformationFormat("Redirect URI: {0}",
                    validatedRequest.RedirectUri);                    
            }
            else
            {
                throw new AuthorizeRequestResourceOwnerException("Invalid redirect URI: " + request.redirect_uri);
            }

            // check state
            if (!string.IsNullOrWhiteSpace(request.state))
            {
                validatedRequest.State = request.state;
                Tracing.Information("State: " + validatedRequest.State);
            }
            else
            {
                Tracing.Information("No state supplied.");
            }

            // validate response type
            if (String.IsNullOrWhiteSpace(request.response_type))
            {
                throw new AuthorizeRequestClientException(
                    "response_type is null or empty",
                    new Uri(validatedRequest.RedirectUri),
                    OAuth2Constants.Errors.InvalidRequest,
                    string.Empty,
                    validatedRequest.State);
            }

            // check response type (only code and token are supported)
            if (!request.response_type.Equals(OAuth2Constants.ResponseTypes.Token, StringComparison.Ordinal) &&
                !request.response_type.Equals(OAuth2Constants.ResponseTypes.Code, StringComparison.Ordinal))
            {
                throw new AuthorizeRequestClientException(
                    "response_type is not token or code: " + request.response_type,
                    new Uri(validatedRequest.RedirectUri),
                    OAuth2Constants.Errors.UnsupportedResponseType,
                    string.Empty,
                    validatedRequest.State);
            }

            validatedRequest.ResponseType = request.response_type;
            Tracing.Information("Response type: " + validatedRequest.ResponseType);

            // scope is required
            if (string.IsNullOrWhiteSpace(request.scope))
            {
                throw new AuthorizeRequestClientException(
                    "Missing scope",
                    new Uri(validatedRequest.RedirectUri),
                    OAuth2Constants.Errors.InvalidScope,
                    validatedRequest.ResponseType,
                    validatedRequest.State);
            }

            // validate scopes
            if (!request.scope.StartsWith("openid"))
            {
                throw new AuthorizeRequestClientException(
                    "Invalid scope: " + request.scope,
                    new Uri(validatedRequest.RedirectUri),
                    OAuth2Constants.Errors.InvalidScope,
                    validatedRequest.ResponseType,
                    validatedRequest.State);
            }

            validatedRequest.Scopes = request.scope; 

            if (request.response_type == OAuth2Constants.ResponseTypes.Code)
            {
                ValidateCodeResponseType(validatedRequest, request);
            }
            else if (request.response_type == OAuth2Constants.ResponseTypes.Token)
            {
                ValidateTokenResponseType(validatedRequest, request);
            }
            else
            {
                throw new AuthorizeRequestClientException(
                    "Invalid response_type: " + request.response_type,
                    new Uri(validatedRequest.RedirectUri),
                    OAuth2Constants.Errors.UnsupportedResponseType,
                    request.response_type,
                    validatedRequest.State);
            }

            return validatedRequest;
        }
 private void ValidateCodeResponseType(ValidatedRequest validatedRequest, AuthorizeRequest request)
 {
     if (validatedRequest.Client.Flow != OpenIdConnectFlows.AuthorizationCode)
     {
         throw new AuthorizeRequestClientException(
            "response_type is not allowed: " + request.response_type,
            new Uri(validatedRequest.RedirectUri),
            OAuth2Constants.Errors.UnsupportedResponseType,
            request.response_type,
            validatedRequest.State);
     }
 }
 private void ValidateTokenResponseType(ValidatedRequest validatedRequest, AuthorizeRequest request)
 {
     throw new NotImplementedException();
 }
        public ValidatedRequest Validate(TokenRequest request, ClaimsPrincipal clientPrincipal)
        {
            var validatedRequest = new ValidatedRequest();

            // validate request model binding
            if (request == null)
            {
                throw new TokenRequestValidationException(
                    "Invalid request parameters.",
                    OAuth2Constants.Errors.InvalidRequest);
            }

            // grant type is required
            if (string.IsNullOrWhiteSpace(request.Grant_Type))
            {
                throw new TokenRequestValidationException(
                    "Missing grant_type",
                    OAuth2Constants.Errors.UnsupportedGrantType);
            }

            // check supported grant types
            if (request.Grant_Type == OAuth2Constants.GrantTypes.AuthorizationCode ||
                request.Grant_Type == OAuth2Constants.GrantTypes.RefreshToken)
            {
                validatedRequest.GrantType = request.Grant_Type;
                Tracing.Information("Grant type: " + validatedRequest.GrantType);
            }
            else
            {
                throw new TokenRequestValidationException(
                    "Invalid grant_type: " + request.Grant_Type,
                    OAuth2Constants.Errors.UnsupportedGrantType);
            }

            // validate client credentials
            var client = ValidateClient(clientPrincipal);
            if (client == null)
            {
                throw new TokenRequestValidationException(
                    "Invalid client: " + clientPrincipal.Identity.Name,
                    OAuth2Constants.Errors.InvalidClient);
            }

            validatedRequest.Client = client;
            Tracing.InformationFormat("Client: {0} ({1})",
                validatedRequest.Client.Name,
                validatedRequest.Client.ClientId);

            switch (request.Grant_Type)
            {
                case OAuth2Constants.GrantTypes.AuthorizationCode:
                    ValidateCodeGrant(validatedRequest, request);
                    break;
                case OAuth2Constants.GrantTypes.RefreshToken:
                    ValidateRefreshTokenGrant(validatedRequest, request);
                    break;
                default:
                    throw new TokenRequestValidationException(
                        "Invalid grant_type: " + request.Grant_Type,
                        OAuth2Constants.Errors.UnsupportedGrantType);
            }

            Tracing.Information("Token request validation successful.");
            return validatedRequest;
        }
        private void ValidateCodeGrant(ValidatedRequest validatedRequest, TokenRequest request)
        {
            if (!validatedRequest.Client.AllowCodeFlow)
            {
                throw new TokenRequestValidationException(
                    "Code flow not allowed for client",
                    OAuth2Constants.Errors.UnauthorizedClient);
            }

            // code needs to be present
            if (string.IsNullOrWhiteSpace(request.Code))
            {
                throw new TokenRequestValidationException(
                    "Missing authorization code",
                    OAuth2Constants.Errors.InvalidGrant);
            }

            //validatedRequest.AuthorizationCode = request.Code;
            Tracing.Information("Authorization code: " + request.Code);

            // check for authorization code in datastore
            var grant = Grants.Get(request.Code);
            if (grant == null)
            {
                throw new TokenRequestValidationException(
                    "Authorization code not found: " + request.Code,
                    OAuth2Constants.Errors.InvalidGrant);
            }

            // make sure the handle is an authorization code
            if (grant.GrantType != StoredGrantType.AuthorizationCode)
            {
                throw new TokenRequestValidationException(
                    "Tampered authorization code: " + request.Code,
                    OAuth2Constants.Errors.InvalidGrant);
            }

            validatedRequest.Grant = grant;
            Tracing.Information("Token handle found: " + grant.GrantId);

            // check the client binding
            if (grant.ClientId != validatedRequest.Client.ClientId)
            {
                throw new TokenRequestValidationException(
                    string.Format("Client {0} is trying to request token using an authorization code from {1}.", validatedRequest.Client.ClientId, grant.ClientId),
                    OAuth2Constants.Errors.InvalidGrant);
            }

            // redirect URI is required
            if (string.IsNullOrWhiteSpace(request.Redirect_Uri))
            {
                throw new TokenRequestValidationException(
                    string.Format("Redirect URI is missing"),
                    OAuth2Constants.Errors.InvalidRequest);
            }

            // check if redirect URI from authorize and token request match
            if (!grant.RedirectUri.Equals(request.Redirect_Uri))
            {
                throw new TokenRequestValidationException(
                    string.Format("Redirect URI in token request ({0}), does not match redirect URI from authorize request ({1})", validatedRequest.RedirectUri, grant.RedirectUri),
                    OAuth2Constants.Errors.InvalidRequest);
            }
        }
        private void ValidateRefreshTokenGrant(ValidatedRequest validatedRequest, TokenRequest request)
        {
            if (!validatedRequest.Client.AllowRefreshToken)
            {
                throw new TokenRequestValidationException(
                    "Refresh token not allowed for client",
                    OAuth2Constants.Errors.UnauthorizedClient);
            }

            // code needs to be present
            if (string.IsNullOrWhiteSpace(request.Refresh_Token))
            {
                throw new TokenRequestValidationException(
                    "Missing refresh token",
                    OAuth2Constants.Errors.InvalidGrant);
            }

            Tracing.Information("Refresh token: " + request.Refresh_Token);

            // check for authorization code in datastore
            var grant = Grants.Get(request.Refresh_Token);
            if (grant == null)
            {
                throw new TokenRequestValidationException(
                    "Refresh token not found: " + request.Refresh_Token,
                    OAuth2Constants.Errors.InvalidGrant);
            }

            // make sure the handle is an authorization code
            if (grant.GrantType != StoredGrantType.RefreshToken)
            {
                throw new TokenRequestValidationException(
                    "Tampered refresh token: " + request.Refresh_Token,
                    OAuth2Constants.Errors.InvalidGrant);
            }

            validatedRequest.Grant = grant;
            Tracing.Information("Stored grant found: " + grant.GrantId);

            // check the client binding
            if (grant.ClientId != validatedRequest.Client.ClientId)
            {
                throw new TokenRequestValidationException(
                    string.Format("Client {0} is trying to request a token using a refresh token from {1}.", validatedRequest.Client.ClientId, grant.ClientId),
                    OAuth2Constants.Errors.InvalidGrant);
            }
        }
 public OidcViewModel(ValidatedRequest validatedRequest)
 {
     if (validatedRequest == null) throw new ArgumentNullException("validatedRequest");
     this.ValidatedRequest = validatedRequest;
     ValidateScopes(GetRawScopes());
 }
 private ActionResult PerformImplicitGrant(ValidatedRequest validatedRequest)
 {
     throw new NotImplementedException();
 }
 protected virtual ActionResult DenyGrant(ValidatedRequest validatedRequest)
 {
     return new ClientErrorResult(new Uri(validatedRequest.RedirectUri), OAuth2Constants.Errors.AccessDenied, validatedRequest.ResponseType, validatedRequest.State);
 }
 protected abstract ActionResult ShowConsent(ValidatedRequest validatedRequest);
 protected virtual ActionResult PerformImplicitGrant(ValidatedRequest validatedRequest)
 {
     throw new NotImplementedException();
 }