/// <summary>
        /// Approves an authorization request.
        /// </summary>
        /// <param name="authorizationRequest">The authorization request to approve.</param>
        /// <param name="userDataAndNonce">The username of the account that approved the request (or whose data will be accessed by the client).</param>
        /// <param name="nonce">The nonce data.</param>
        /// <param name="successAccessTokenResponse">The end user authorization success access token response.</param>
        /// <param name="scopes">The scope of access the client should be granted.  If <c>null</c>, all scopes in the original request will be granted.</param>
        /// <param name="callback">The Client callback URL to use when formulating the redirect to send the user agent back to the Client.</param>
        /// <returns>The authorization response message to send to the Client.</returns>
        public EndUserAuthorizationSuccessResponseBase PrepareApproveAuthorizationRequest(EndUserAuthorizationRequest authorizationRequest,
                                                                                          string userDataAndNonce, string nonce, out EndUserAuthorizationSuccessAccessTokenResponse successAccessTokenResponse, IEnumerable <string> scopes = null, Uri callback = null)
        {
            Contract.Ensures(Contract.Result <EndUserAuthorizationSuccessResponseBase>() != null);

            if (callback == null)
            {
                callback = this.GetCallback(authorizationRequest);
            }

            var client = this.AuthorizationServerServices.GetClientOrThrow(authorizationRequest.ClientIdentifier);
            EndUserAuthorizationSuccessResponseBase        response;
            EndUserAuthorizationSuccessAccessTokenResponse implicitGrantResponse = null;

            switch (authorizationRequest.ResponseType)
            {
            case EndUserAuthorizationResponseType.AccessToken:
                IAccessTokenRequestInternal accessRequestInternal = (EndUserAuthorizationImplicitRequest)authorizationRequest;
                var accessTokenResult = this.AuthorizationServerServices.CreateAccessToken(accessRequestInternal, nonce);
                ErrorUtilities.VerifyHost(accessTokenResult != null, "IAuthorizationServerHost.CreateAccessToken must not return null.");

                accessRequestInternal.AccessTokenResult = accessTokenResult;

                implicitGrantResponse          = new EndUserAuthorizationSuccessAccessTokenResponse(callback, authorizationRequest);
                implicitGrantResponse.Lifetime = accessTokenResult.AccessToken.Lifetime;
                accessTokenResult.AccessToken.ApplyAuthorization(implicitGrantResponse.Scope, userDataAndNonce, implicitGrantResponse.Lifetime);

                IAccessTokenCarryingRequest tokenCarryingResponse = implicitGrantResponse;
                tokenCarryingResponse.AuthorizationDescription = accessTokenResult.AccessToken;

                response = implicitGrantResponse;
                break;

            case EndUserAuthorizationResponseType.AuthorizationCode:
                var authCodeResponse = new EndUserAuthorizationSuccessAuthCodeResponseAS(callback, authorizationRequest);
                IAuthorizationCodeCarryingRequest codeCarryingResponse = authCodeResponse;
                codeCarryingResponse.AuthorizationDescription = new AuthorizationCode(
                    authorizationRequest.ClientIdentifier,
                    authorizationRequest.Callback,
                    authCodeResponse.Scope,
                    userDataAndNonce);
                response = authCodeResponse;
                break;

            default:
                throw ErrorUtilities.ThrowInternal("Unexpected response type.");
            }

            response.AuthorizingUsername = userDataAndNonce;

            // Customize the approved scope if the authorization server has decided to do so.
            if (scopes != null)
            {
                response.Scope.ResetContents(scopes);
            }

            successAccessTokenResponse = implicitGrantResponse;
            return(response);
        }
Beispiel #2
0
        /// <summary>
        /// Performs any transformation on an incoming message that may be necessary and/or
        /// validates an incoming message based on the rules of this channel binding element.
        /// </summary>
        /// <param name="message">The incoming message to process.</param>
        /// <returns>
        /// The protections (if any) that this binding element applied to the message.
        /// Null if this binding element did not even apply to this binding element.
        /// </returns>
        /// <exception cref="ProtocolException">
        /// Thrown when the binding element rules indicate that this message is invalid and should
        /// NOT be processed.
        /// </exception>
        /// <remarks>
        /// Implementations that provide message protection must honor the
        /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
        /// </remarks>
        public override MessageProtections?ProcessIncomingMessage(IProtocolMessage message)
        {
            bool applied = false;

            // Check that the client secret is correct for client authenticated messages.
            var clientCredentialOnly         = message as AccessTokenClientCredentialsRequest;
            var authenticatedClientRequest   = message as AuthenticatedClientRequestBase;
            var accessTokenRequest           = authenticatedClientRequest as AccessTokenRequestBase;   // currently the only type of message.
            var resourceOwnerPasswordCarrier = message as AccessTokenResourceOwnerPasswordCredentialsRequest;

            if (authenticatedClientRequest != null)
            {
                string clientIdentifier;
                var    result = this.clientAuthenticationModule.TryAuthenticateClient(this.AuthServerChannel.AuthorizationServer, authenticatedClientRequest, out clientIdentifier);
                switch (result)
                {
                case ClientAuthenticationResult.ClientAuthenticated:
                    break;

                case ClientAuthenticationResult.NoAuthenticationRecognized:
                case ClientAuthenticationResult.ClientIdNotAuthenticated:
                    // The only grant type that allows no client credentials is the resource owner credentials grant.
                    AuthServerUtilities.TokenEndpointVerify(resourceOwnerPasswordCarrier != null, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
                    break;

                default:
                    AuthServerUtilities.TokenEndpointVerify(false, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
                    break;
                }

                authenticatedClientRequest.ClientIdentifier = result == ClientAuthenticationResult.NoAuthenticationRecognized ? null : clientIdentifier;
                accessTokenRequest.ClientAuthenticated      = result == ClientAuthenticationResult.ClientAuthenticated;
                applied = true;
            }

            // Check that any resource owner password credential is correct.
            if (resourceOwnerPasswordCarrier != null)
            {
                try {
                    var authorizeResult =
                        this.AuthorizationServer.CheckAuthorizeResourceOwnerCredentialGrant(
                            resourceOwnerPasswordCarrier.UserName, resourceOwnerPasswordCarrier.Password, resourceOwnerPasswordCarrier);
                    if (authorizeResult.IsApproved)
                    {
                        resourceOwnerPasswordCarrier.CredentialsValidated = true;
                        resourceOwnerPasswordCarrier.UserName             = authorizeResult.CanonicalUserName;
                        resourceOwnerPasswordCarrier.Scope.ResetContents(authorizeResult.ApprovedScope);
                    }
                    else
                    {
                        Logger.OAuth.ErrorFormat(
                            "Resource owner password credential for user \"{0}\" rejected by authorization server host.",
                            resourceOwnerPasswordCarrier.UserName);
                        throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidGrant, AuthServerStrings.InvalidResourceOwnerPasswordCredential);
                    }
                } catch (NotSupportedException) {
                    throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
                } catch (NotImplementedException) {
                    throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
                }

                applied = true;
            }
            else if (clientCredentialOnly != null)
            {
                try {
                    var authorizeResult = this.AuthorizationServer.CheckAuthorizeClientCredentialsGrant(clientCredentialOnly);
                    if (!authorizeResult.IsApproved)
                    {
                        Logger.OAuth.ErrorFormat(
                            "Client credentials grant access request for client \"{0}\" rejected by authorization server host.",
                            clientCredentialOnly.ClientIdentifier);
                        throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnauthorizedClient);
                    }

                    clientCredentialOnly.Scope.ResetContents(authorizeResult.ApprovedScope);
                } catch (NotSupportedException) {
                    throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
                } catch (NotImplementedException) {
                    throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.UnsupportedGrantType);
                }
            }
            else
            {
                // Check that authorization requests come with an acceptable callback URI.
                var authorizationRequest = message as EndUserAuthorizationRequest;
                if (authorizationRequest != null)
                {
                    var client = this.AuthorizationServer.GetClientOrThrow(authorizationRequest.ClientIdentifier);
                    ErrorUtilities.VerifyProtocol(authorizationRequest.Callback == null || client.IsCallbackAllowed(authorizationRequest.Callback), AuthServerStrings.ClientCallbackDisallowed, authorizationRequest.Callback);
                    ErrorUtilities.VerifyProtocol(authorizationRequest.Callback != null || client.DefaultCallback != null, AuthServerStrings.NoCallback);
                    applied = true;
                }

                // Check that the callback URI in a direct message from the client matches the one in the indirect message received earlier.
                var request = message as AccessTokenAuthorizationCodeRequestAS;
                if (request != null)
                {
                    IAuthorizationCodeCarryingRequest tokenRequest = request;
                    tokenRequest.AuthorizationDescription.VerifyCallback(request.Callback);
                    applied = true;
                }

                var authCarrier = message as IAuthorizationCarryingRequest;
                if (authCarrier != null)
                {
                    var accessRequest = authCarrier as AccessTokenRequestBase;
                    if (accessRequest != null)
                    {
                        // Make sure the client sending us this token is the client we issued the token to.
                        AuthServerUtilities.TokenEndpointVerify(string.Equals(accessRequest.ClientIdentifier, authCarrier.AuthorizationDescription.ClientIdentifier, StringComparison.Ordinal), accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient);

                        var scopedAccessRequest = accessRequest as ScopedAccessTokenRequest;
                        if (scopedAccessRequest != null)
                        {
                            // Make sure the scope the client is requesting does not exceed the scope in the grant.
                            if (!this.AuthServerChannel.ScopeSatisfiedCheck.IsScopeSatisfied(requiredScope: scopedAccessRequest.Scope, grantedScope: authCarrier.AuthorizationDescription.Scope))
                            {
                                Logger.OAuth.ErrorFormat("The requested access scope (\"{0}\") exceeds the grant scope (\"{1}\").", scopedAccessRequest.Scope, authCarrier.AuthorizationDescription.Scope);
                                throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidScope, AuthServerStrings.AccessScopeExceedsGrantScope);
                            }
                        }
                    }

                    // Make sure the authorization this token represents hasn't already been revoked.
                    if (!this.AuthorizationServer.IsAuthorizationValid(authCarrier.AuthorizationDescription))
                    {
                        Logger.OAuth.Error("Rejecting access token request because the IAuthorizationServerHost.IsAuthorizationValid method returned false.");
                        throw new TokenEndpointProtocolException(accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidGrant);
                    }

                    applied = true;
                }
            }

            return(applied ? (MessageProtections?)MessageProtections.None : null);
        }