예제 #1
0
        /// <summary>
        /// Refreshes the OAuth 2.0 access token using the refresh token provided.
        /// </summary>
        /// <param name="pluginConfiguration">The configuration for the OAuth 2.0 identity provider.</param>
        /// <param name="refreshToken">The refresh token.</param>
        /// <param name="setHttpHeaders">If true, <see cref="AddAuthorizationHeader"/> will be called automatically.</param>
        /// <param name="token">A cancellation token for the task.</param>
        /// <returns>The updated access token data.</returns>
        public async Task <OAuth2TokenResponse> RefreshOAuth2TokenAsync(
            OAuth2Configuration pluginConfiguration,
            string refreshToken,
            bool setHttpHeaders     = true,
            CancellationToken token = default(CancellationToken))
        {
            // Sanity.
            if (null == pluginConfiguration)
            {
                throw new ArgumentNullException(nameof(pluginConfiguration));
            }
            if (string.IsNullOrWhiteSpace(refreshToken))
            {
                throw new ArgumentException("The OAuth 2.0 refresh token cannot be empty.", nameof(refreshToken));
            }

            // Create the request, adding the mandatory items.
            var tokenEndpoint = new Uri(pluginConfiguration.TokenEndpoint, uriKind: UriKind.Absolute);
            var request       = new RestSharp.RestRequest(tokenEndpoint.PathAndQuery, RestSharp.Method.POST);

            request.AddParameter("grant_type", "refresh_token");
            request.AddParameter("refresh_token", refreshToken);
            request.AddParameter("redirect_uri", pluginConfiguration.GetAppropriateRedirectUri());

            // Add the client id.  If there's a realm then use that here too.
            request.AddParameter(
                "client_id",
                string.IsNullOrWhiteSpace(pluginConfiguration.SiteRealm)
                                        ? pluginConfiguration.ClientID                                      // If no site realm is supplied, just pass the client ID.
                                        : $"{pluginConfiguration.ClientID}@{pluginConfiguration.SiteRealm}" // Otherwise pass client ID @ site realm.
                );

            // Add the optional bits.
            request.AddParameterIfNotNullOrWhitespace("resource", pluginConfiguration.Resource);
            request.AddParameterIfNotNullOrWhitespace("scope", pluginConfiguration.Scope);
            request.AddParameterIfNotNullOrWhitespace("client_secret", pluginConfiguration.ClientSecret);

            // Make a post to the token endpoint.
            // NOTE: We must use a new RestClient here otherwise it'll try and add the token endpoint to the MFWA base url.
            var restClient = new RestSharp.RestClient(tokenEndpoint.GetLeftPart(UriPartial.Authority));
            var response   = await restClient.ExecutePostAsync <OAuth2TokenResponse>(request, token);

            // Validate response.
            if (null == response.Data ||
                response.Data.TokenType != "Bearer")
            {
                throw new InvalidOperationException("OAuth token not received from endpoint, or token type was not bearer.");
            }

            // Set the authorisation header.
            if (setHttpHeaders)
            {
                this.AddAuthorizationHeader(pluginConfiguration, response.Data);
            }

            // Return the access token data.
            return(response.Data);
        }
예제 #2
0
        /// <summary>
        /// Extracts data from the <paramref name="redirectUri"/> and uses it to retrieve access
        /// and refresh tokens from the provider.
        /// </summary>
        /// <param name="redirectUri">The Uri redirected to by the provider.</param>
        /// <returns>The token response, if /*available*/.</returns>
        private async Task <OAuth2TokenResponse> ProcessRedirectUri(Uri redirectUri)
        {
            // Does this represent an error?
            var queryParams = new UriBuilder(redirectUri).GetQueryParamsDictionary();

            if (queryParams.ContainsKey("error"))
            {
                throw new InvalidOperationException
                      (
                          $"Exception {queryParams["error"]} returned by authorisation endpoint."
                      );
            }

            // Check that the state was correct (not tampered with).
            if (this.oAuthPluginInfo.Configuration["state"]?.ToString() != queryParams["state"])
            {
                throw new InvalidOperationException
                      (
                          "The state returned by the authorisation endpoint was not correct."
                      );
            }

            // Retrieve the authorisation code from the URI.
            var code = queryParams.ContainsKey("code") ? queryParams["code"] : null;

            // Convert the authorisation code to tokens.

            // Create the request, adding the mandatory items.
            var tokenEndpoint = new Uri(this.oAuthPluginInfo.GetTokenEndpoint(), uriKind: UriKind.Absolute);
            var request       = new RestSharp.RestRequest(tokenEndpoint.PathAndQuery, RestSharp.Method.POST);

            request.AddParameter("code", code);
            request.AddParameter("grant_type", "authorization_code");
            request.AddParameter("redirect_uri", this.oAuthPluginInfo.GetAppropriateRedirectUri());

            // Add the client id.  If there's a realm then use that here too.
            {
                var siteRealm = this.oAuthPluginInfo.GetSiteRealm();
                var clientId  = this.oAuthPluginInfo.GetClientID();
                request.AddParameter
                (
                    "client_id",
                    string.IsNullOrWhiteSpace(siteRealm)
                                                ? clientId                  // If no site realm is supplied, just pass the client ID.
                                                : $"{clientId}@{siteRealm}" // Otherwise pass client ID @ site realm.
                );
            }

            // Add the optional bits.
            request
            .AddParameterIfNotNullOrWhitespace("resource", this.oAuthPluginInfo.GetResource())
            .AddParameterIfNotNullOrWhitespace("scope", this.oAuthPluginInfo.GetScope())
            .AddParameterIfNotNullOrWhitespace("client_secret", this.oAuthPluginInfo.GetClientSecret());

            // Execute the HTTP request.
            var restClient = new RestSharp.RestClient(tokenEndpoint.GetLeftPart(UriPartial.Authority));
            var response   = await restClient.ExecutePostAsync <OAuth2TokenResponse>(request);

            // Validate response.
            if (null == response.Data)
            {
                throw new InvalidOperationException("OAuth token not received from endpoint. Response: " + response.Content);
            }
            else if (response.Data.TokenType != "Bearer")
            {
                throw new InvalidOperationException("Token type was not bearer. Response: " + response.Content);
            }

            // Return the access token data.
            return(response.Data);
        }