We’ve been using the ServiceStack MicrosoftGraphAuthProvider
successfully for some time, however a recent update to the Client Secret caused the authentication to stop working for all users. The sign-in attempt fails, and the browser ends up at the URL /#f=Unknown relative to the site root. The Client Secret is in this format.
We noticed that the new Client Secret contained a plus character where the old one did not, which appears to be the cause of the problem. The HTTP POST request which attempts to acquire an access token is URL encoding the redirect_uri
parameter, but does not appear to be encoding the client_secret
parameter. We were able to work around the issue by manually URL encoding the new secret in our application configuration (replacing the ‘+’ with ‘%2b’), at which point users could sign-in successfully.
Is there any way to configure the MicrosoftGraphAuthProvider
so that it URL encodes the client_secret
parameter?
Edit : I’ve found where the token is being requested in the source code and in doing so, have answered my original question – it can’t be configured to URL encode the secret.
From the MicrosoftGraphAuthProvider
source code :
protected override async Task<string> GetAccessTokenJsonAsync
(string code, AuthContext ctx, CancellationToken token = default)
{
var accessTokenParams =
$"code={code}&client_id={ConsumerKey}&client_secret={ConsumerSecret}&redirect_uri={this.CallbackUrl.UrlEncode()}&grant_type=authorization_code";
var contents = await AccessTokenUrlFilter(ctx, AccessTokenUrl)
.SendStringToUrlAsync(method:HttpMethods.Post, requestBody:accessTokenParams, contentType: MimeTypes.FormUrlEncoded, token: token).ConfigAwait();
return contents;
}
5
The problem you’re experiencing is due to the client_secret
not being URL-encoded when included in the token request. Special characters like +
need to be properly encoded as %2B
to ensure the request is processed correctly by Microsoft Graph.
To resolve this, you can manually encode the client_secret
before passing it into the MicrosoftGraphAuthProvider
. Here’s how you can do it:
var encodedSecret = Uri.EscapeDataString(appSettings.GetString("oauth.microsoftgraph.AppSecret"));
authProvider.AppSecret = encodedSecret;
This ensures that any special characters in the client_secret
are properly encoded, and you won’t run into issues caused by characters like +
.
In your case, you can make use of below modified code as you mentioned in question edit:
From the MicrosoftGraphAuthProvider
source code :
protected override async Task<string> GetAccessTokenJsonAsync
(string code, AuthContext ctx, CancellationToken token = default)
{
var accessTokenParams =
$"code={code}&client_id={ConsumerKey}&client_secret={ConsumerSecret.UrlEncode()}&redirect_uri={this.CallbackUrl.UrlEncode()}&grant_type=authorization_code";
var contents = await AccessTokenUrlFilter(ctx, AccessTokenUrl)
.SendStringToUrlAsync(
method: HttpMethods.Post,
requestBody: accessTokenParams,
contentType: MimeTypes.FormUrlEncoded,
token: token
).ConfigAwait();
return contents;
}