/// <summary> /// Using the <see cref="code"/> from the OAuth authorisation endpoint, /// requests tokens from the token endpoint and sets up the client to use them. /// The token data is returned in case it is needed in the future (e.g. <see cref="RefreshOAuth2TokenAsync(MFaaP.MFWSClient.OAuth2.OAuth2Configuration,MFaaP.MFWSClient.OAuth2.OAuth2TokenResponse,bool,System.Threading.CancellationToken)"/>). /// </summary> /// <param name="pluginConfiguration">The configuration of the OAuth plugin.</param> /// <param name="code">The code returned from the OAuth authorisation endpoint.</param> /// <param name="cancellationToken">A cancellation token for the task.</param> /// <returns>The data returned from the token endpoint.</returns> protected async Task <OAuth2TokenResponse> ConvertOAuth2AuthorizationCodeToTokensAsync( OAuth2Configuration pluginConfiguration, string code, CancellationToken cancellationToken = default(CancellationToken)) { // Sanity. if (null == pluginConfiguration) { throw new ArgumentNullException(nameof(pluginConfiguration)); } if (null == code) { throw new ArgumentNullException(nameof(code)); } // 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("code", code); request.AddParameter("grant_type", pluginConfiguration.GrantType); 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.ExecutePostTaskAsync <OAuth2TokenResponse>(request, cancellationToken); // 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."); } // Return the access token data. return(response.Data); }