Provides context information used at the end of a token-endpoint-request.
Inheritance: BaseOAuthEndpointContext
Ejemplo n.º 1
0
        private async Task InvokeTokenEndpointAsync()
        {
            DateTimeOffset currentUtc = Options.SystemClock.UtcNow;

            // remove milliseconds in case they don't round-trip
            currentUtc = currentUtc.Subtract(TimeSpan.FromMilliseconds(currentUtc.Millisecond));

            IFormCollection form = await Request.ReadFormAsync();

            var clientContext = new OAuthValidateClientAuthenticationContext(Context, Options, form);

            await Options.Provider.ValidateClientAuthentication(clientContext);

            if (!clientContext.IsValidated)
            {
                Logger.LogError("clientID is not valid.");

                if (!clientContext.HasError)
                {
                    clientContext.SetError(Constants.Errors.InvalidClient);
                }

                await SendErrorAsJsonAsync(clientContext);

                return;
            }

            var tokenEndpointRequest = new TokenEndpointRequest(form);

            var validatingContext = new OAuthValidateTokenRequestContext(Context, Options, tokenEndpointRequest, clientContext);

            AuthenticationTicket ticket = null;

            if (tokenEndpointRequest.IsAuthorizationCodeGrantType)
            {
                // Authorization Code Grant http://tools.ietf.org/html/rfc6749#section-4.1
                // Access Token Request http://tools.ietf.org/html/rfc6749#section-4.1.3
                ticket = await InvokeTokenEndpointAuthorizationCodeGrantAsync(validatingContext, currentUtc);
            }
            else if (tokenEndpointRequest.IsResourceOwnerPasswordCredentialsGrantType)
            {
                // Resource Owner Password Credentials Grant http://tools.ietf.org/html/rfc6749#section-4.3
                // Access Token Request http://tools.ietf.org/html/rfc6749#section-4.3.2
                ticket = await InvokeTokenEndpointResourceOwnerPasswordCredentialsGrantAsync(validatingContext, currentUtc);
            }
            else if (tokenEndpointRequest.IsClientCredentialsGrantType)
            {
                // Client Credentials Grant http://tools.ietf.org/html/rfc6749#section-4.4
                // Access Token Request http://tools.ietf.org/html/rfc6749#section-4.4.2
                ticket = await InvokeTokenEndpointClientCredentialsGrantAsync(validatingContext, currentUtc);
            }
            else if (tokenEndpointRequest.IsRefreshTokenGrantType)
            {
                // Refreshing an Access Token
                // http://tools.ietf.org/html/rfc6749#section-6
                ticket = await InvokeTokenEndpointRefreshTokenGrantAsync(validatingContext, currentUtc);
            }
            else if (tokenEndpointRequest.IsCustomExtensionGrantType)
            {
                // Defining New Authorization Grant Types
                // http://tools.ietf.org/html/rfc6749#section-8.3
                ticket = await InvokeTokenEndpointCustomGrantAsync(validatingContext, currentUtc);
            }
            else
            {
                // Error Response http://tools.ietf.org/html/rfc6749#section-5.2
                // The authorization grant type is not supported by the
                // authorization server.
                Logger.LogError("grant type is not recognized");

                validatingContext.SetError(Constants.Errors.UnsupportedGrantType);
            }

            if (ticket == null)
            {
                await SendErrorAsJsonAsync(validatingContext);

                return;
            }

            ticket.Properties.IssuedUtc  = currentUtc;
            ticket.Properties.ExpiresUtc = currentUtc.Add(Options.AccessTokenExpireTimeSpan);

            var tokenEndpointContext = new OAuthTokenEndpointContext(Context, Options, ticket, tokenEndpointRequest);

            await Options.Provider.TokenEndpoint(tokenEndpointContext);

            if (tokenEndpointContext.TokenIssued)
            {
                ticket = new AuthenticationTicket(tokenEndpointContext.Principal, tokenEndpointContext.Properties, tokenEndpointContext.Options.AuthenticationScheme);
            }
            else
            {
                Logger.LogError("Token was not issued to tokenEndpointContext");
                validatingContext.SetError(Constants.Errors.InvalidGrant);
                await SendErrorAsJsonAsync(validatingContext);

                return;
            }

            var accessTokenContext = new AuthenticationTokenCreateContext(
                Context,
                Options.AccessTokenFormat,
                ticket);

            await Options.AccessTokenProvider.CreateAsync(accessTokenContext);

            string accessToken = accessTokenContext.Token;

            if (string.IsNullOrEmpty(accessToken))
            {
                accessToken = accessTokenContext.SerializeTicket();
            }

            DateTimeOffset?accessTokenExpiresUtc = ticket.Properties.ExpiresUtc;

            var refreshTokenCreateContext = new AuthenticationTokenCreateContext(Context, Options.RefreshTokenFormat, accessTokenContext.Ticket);

            await Options.RefreshTokenProvider.CreateAsync(refreshTokenCreateContext);

            string refreshToken = refreshTokenCreateContext.Token;

            var tokenEndpointResponseContext = new OAuthTokenEndpointResponseContext(Context, Options, ticket, tokenEndpointRequest, accessToken, tokenEndpointContext.AdditionalResponseParameters);

            await Options.Provider.TokenEndpointResponse(tokenEndpointResponseContext);

            MemoryStream stream, memoryStream = null;

            string body;

            try
            {
                stream = memoryStream = new MemoryStream();

                using (var writer = new JsonTextWriter(new StreamWriter(memoryStream)))
                {
                    memoryStream = null;

                    writer.WriteStartObject();
                    writer.WritePropertyName(Constants.Parameters.AccessToken);
                    writer.WriteValue(accessToken);
                    writer.WritePropertyName(Constants.Parameters.TokenType);
                    writer.WriteValue(Constants.TokenTypes.Bearer);

                    if (accessTokenExpiresUtc.HasValue)
                    {
                        TimeSpan?expiresTimeSpan = accessTokenExpiresUtc - currentUtc;
                        var      expiresIn       = (long)expiresTimeSpan.Value.TotalSeconds;
                        if (expiresIn > 0)
                        {
                            writer.WritePropertyName(Constants.Parameters.ExpiresIn);
                            writer.WriteValue(expiresIn);
                        }
                    }

                    if (!string.IsNullOrEmpty(refreshToken))
                    {
                        writer.WritePropertyName(Constants.Parameters.RefreshToken);
                        writer.WriteValue(refreshToken);
                    }

                    foreach (var additionalResponseParameter in tokenEndpointResponseContext.AdditionalResponseParameters)
                    {
                        writer.WritePropertyName(additionalResponseParameter.Key);
                        writer.WriteValue(additionalResponseParameter.Value);
                    }

                    writer.WriteEndObject();
                    writer.Flush();
                    body = Encoding.UTF8.GetString(stream.ToArray());

                    Response.ContentType = "application/json;charset=UTF-8";
                    Response.Headers["Cache-Control"] = "no-cache";
                    Response.Headers["Pragma"]        = "no-cache";
                    Response.Headers["Expires"]       = "-1";
                    Response.ContentLength            = Encoding.UTF8.GetByteCount(body);
                }
            }
            finally
            {
                if (memoryStream != null)
                {
                    memoryStream.Dispose();
                }
            }

            await Response.WriteAsync(body, Encoding.UTF8, Context.RequestAborted);
        }
 /// <summary>
 /// Called before the TokenEndpoint redirects its response to the caller. 
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 public virtual Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
 {
     return OnTokenEndpointResponse.Invoke(context);
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Called before the TokenEndpoint redirects its response to the caller.
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 public virtual Task TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
 {
     return(OnTokenEndpointResponse.Invoke(context));
 }