Exemple #1
0
        /// <summary>Asynchronously authorizes the web application to access user's protected data.</summary>
        /// <param name="userId">User identifier</param>
        /// <param name="taskCancellationToken">Cancellation token to cancel an operation</param>
        /// <returns>
        /// Auth result object which contains the user's credential or redirect URI for the authorization server
        /// </returns>
        public async Task <AuthResult> AuthorizeAsync(string userId, CancellationToken taskCancellationToken)
        {
            // Try to load a token from the data store.
            var token = await Flow.LoadTokenAsync(userId, taskCancellationToken).ConfigureAwait(false);

            // If the stored token is null or it doesn't have a refresh token and the access token is expired, we need
            // to retrieve a new access token.
            if (token == null || (token.RefreshToken == null && token.IsExpired(flow.Clock)))
            {
                // Create a authorization code request.
                AuthorizationCodeRequestUrl codeRequest = Flow.CreateAuthorizationCodeRequest(redirectUri);

                // Add a random number to the end of the state so we can indicate the original request was made by this
                // call.
                var oauthState = state;
                if (Flow.DataStore != null)
                {
                    var rndString = new string('9', StateRandomLength);
                    var random    = new Random().Next(int.Parse(rndString)).ToString("D" + StateRandomLength);
                    oauthState += random;
                    await Flow.DataStore.StoreAsync(StateKey + userId, oauthState).ConfigureAwait(false);
                }
                codeRequest.State = oauthState;

                return(new AuthResult {
                    RedirectUri = codeRequest.Build().ToString()
                });
            }

            return(new AuthResult {
                Credential = new UserCredential(flow, userId, token)
            });
        }
        /// <inheritdoc/>
        public async Task <UserCredential> AuthorizeAsync(string userId, CancellationToken taskCancellationToken)
        {
            // Try to load a token from the data store.
            var token = await Flow.LoadTokenAsync(userId, taskCancellationToken).ConfigureAwait(false);

            // Check if a new authorization code is needed.
            if (ShouldRequestAuthorizationCode(token))
            {
                // Create an authorization code request.
                var redirectUri = CodeReceiver.RedirectUri;
                AuthorizationCodeRequestUrl codeRequest = Flow.CreateAuthorizationCodeRequest(redirectUri);

                // Receive the code.
                var response = await CodeReceiver.ReceiveCodeAsync(codeRequest, taskCancellationToken)
                               .ConfigureAwait(false);

                if (string.IsNullOrEmpty(response.Code))
                {
                    var errorResponse = new TokenErrorResponse(response);
                    Logger.Info("Received an error. The response is: {0}", errorResponse);
                    throw new TokenResponseException(errorResponse);
                }

                Logger.Debug("Received \"{0}\" code", response.Code);

                // Get the token based on the code.
                token = await Flow.ExchangeCodeForTokenAsync(userId, response.Code, redirectUri,
                                                             taskCancellationToken).ConfigureAwait(false);
            }

            return(new UserCredential(flow, userId, token));
        }
Exemple #3
0
        /// <summary>Asynchronously authorizes the web application to access user's protected data.</summary>
        /// <param name="userId">User identifier</param>
        /// <param name="taskCancellationToken">Cancellation token to cancel an operation</param>
        /// <returns>
        /// Auth result object which contains the user's credential or redirect URI for the authorization server
        /// </returns>
        public async Task <AuthResult> AuthorizeAsync(string userId, CancellationToken taskCancellationToken)
        {
            // Try to load a token from the data store.
            var token = await Flow.LoadTokenAsync(userId, taskCancellationToken).ConfigureAwait(false);

            // Check if a new authorization code is needed.
            if (ShouldRequestAuthorizationCode(token))
            {
                // Create an authorization code request.
                AuthorizationCodeRequestUrl codeRequest = Flow.CreateAuthorizationCodeRequest(redirectUri);

                // Add a random number to the end of the state so we can indicate the original request was made by this
                // call.
                var oauthState = state;
                if (Flow.DataStore != null)
                {
                    var rndString = new string('9', StateRandomLength);
                    var random    = new Random().Next(int.Parse(rndString)).ToString("D" + StateRandomLength);
                    oauthState += random;
                    await Flow.DataStore.StoreAsync(StateKey + userId, oauthState).ConfigureAwait(false);
                }
                codeRequest.State = oauthState;

                return(new AuthResult {
                    RedirectUri = codeRequest.Build().ToString()
                });
            }

            return(new AuthResult {
                Credential = new UserCredential(flow, userId, token)
            });
        }
        public async Task <UserCredential> AuthorizeAsync(string userId, CancellationToken taskCancellationToken)
        {
            // Try to load a token from the data store.
            var token = await Flow.LoadTokenAsync(userId, taskCancellationToken).ConfigureAwait(false);

            // If the stored token is null or it doesn't have a refresh token and the access token is expired we need
            // to retrieve a new authorization code.
            if (token == null || (token.RefreshToken == null && token.IsExpired(flow.Clock)))
            {
                // Create an authorization code request.
                var redirectUri = CodeReceiver.RedirectUri;
                AuthorizationCodeRequestUrl codeRequest = Flow.CreateAuthorizationCodeRequest(redirectUri);

                // Receive the code.
                var response = await CodeReceiver.ReceiveCodeAsync(codeRequest, taskCancellationToken)
                               .ConfigureAwait(false);

                if (string.IsNullOrEmpty(response.Code))
                {
                    var errorResponse = new TokenErrorResponse(response);
                    Logger.Info("Received an error. The response is: {0}", errorResponse);
                    throw new TokenResponseException(errorResponse);
                }

                Logger.Debug("Received \"{0}\" code", response.Code);

                // Get the token based on the code.
                token = await Flow.ExchangeCodeForTokenAsync(userId, response.Code, CodeReceiver.RedirectUri,
                                                             taskCancellationToken).ConfigureAwait(false);
            }

            return(new UserCredential(flow, userId, token));
        }
Exemple #5
0
        public string RedirectToGoogleAuthorizationPage()
        {
            var codeRequest = Flow.CreateAuthorizationCodeRequest(RedirectUri);

            // TODO: Use a more cryptographically safe nonce generator
            var oauthState = $"{State}{new Random().Next(int.Parse(new string('9', 8))).ToString("D" + 8)}";

            // TODO: What should happen if an OAuth state is already in the database?
            // TODO: For now, upsert
            _context.GoogleOauthStates.AddOrUpdate(
                new GoogleOauthState {
                UserId = UserId, Value = oauthState
            });

            // TODO: Make sure the code request URL can be built before saving the state in the database
            _context.SaveChanges();
            codeRequest.State = oauthState;

            // HACK: Needed to add "&prompt=select_account" to force Google account selection screen
            return($"{codeRequest.Build()}&prompt=select_account+consent");
        }