Hi,
I am wondering if anyone has tried (successfully) to setup OAuth in a Blazor Web Assembly. I think I have things configured based on the documentation but continue to get an error saying it is not setup correct. Without any specifics.
Thanks - joe
I haven't @joe but if you solve it let us know how!!
Thanks and good luck!
In the end is pretty straight forward. The simplest way is to simply get a token directly from a call to the /authorize method. This was done by navigating to the authorize Url in the OnInitialized method of the Index.razor page
protected override void OnInitialized()
{
try
{
string authorizeUrl = "https://www.arcgis.com/sharing/rest/oauth2/authorize";
string clientId = Configuration["Authorization:clientId"]!.ToString();
string redirectUrl = Configuration["Authorization:redirectUrl"]!.ToString();
string responseType = "token";
UriBuilder builder = new UriBuilder(authorizeUrl)
{
Query = $"client_id={clientId}&redirect_uri={redirectUrl}&response_type={responseType}"
};
string oAuthUrl = builder.ToString();
NavigationManager.NavigateTo(oAuthUrl);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
Then in the page defined in the redirectUrl you grab the token from the return returned url
protected override void OnInitialized()
{
try
{
_token = Navigation.Uri.Substring(Navigation.Uri.IndexOf("=", StringComparison.Ordinal) + 1);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
An approach which I think is a bit more secure would involve requesting code from /authorize method and then getting the token in the redirect page using the /token method. In this case in the Index.razor we have
protected override void OnInitialized()
{
try
{
string authorizeUrl = "https://www.arcgis.com/sharing/rest/oauth2/authorize";
string clientId = Configuration["Authorization:clientId"]!.ToString();
string redirectUrl = Configuration["Authorization:redirectUrl"]!.ToString();
string responseType = "code";
string codeChallenge = CreateChallangeCode();
string codeChallengeMethod = "plain";
UriBuilder builder = new UriBuilder(authorizeUrl)
{
Query = $"client_id={clientId}&redirect_uri={redirectUrl}&response_type={responseType}&code_challenge={codeChallenge}&code_challenge_method={codeChallengeMethod}"
};
string oAuthUrl = builder.ToString();
NavigationManager.NavigateTo(oAuthUrl);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private string CreateChallangeCode()
{
using SHA256 sha256 = SHA256.Create();
byte[] data = sha256.ComputeHash(Encoding.UTF8.GetBytes("blazor"));
var builder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
foreach (var b in data)
{
builder.Append(b.ToString("x2"));
}
return builder.ToString();
}
and in the redirect page get the token from the returned code
protected override async void OnInitialized()
{
try
{
string code = Navigation.Uri.Substring(Navigation.Uri.IndexOf("=", StringComparison.Ordinal) + 1);
await RequestToken(code);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private async Task RequestToken(string code)
{
string tokenUrl = "https://www.arcgis.com/sharing/rest/oauth2/token";
string clientId = Configuration["Authorization:clientId"]!;
string redirectUrl = Configuration["Authorization:redirectUrl"]!;
string codeChallenge = CreateCodeChallenge();
var dictionary = new Dictionary<string, string>
{
{ "client_id", clientId },
{ "grant_type", "authorization_code" },
{ "code", code! },
{ "code_verifier", codeChallenge },
{ "redirect_uri", redirectUrl }
};
FormUrlEncodedContent content = new FormUrlEncodedContent(dictionary);
using HttpClient client = new HttpClient();
var response = await client.PostAsync(tokenUrl, content);
var json = await response.Content.ReadAsStringAsync();
JsonNode node = JsonNode.Parse(json)!;
_token = node!["access_token"]!.ToString();
}
Awesome @joe !! thanks for taking the time to share the solution 🙂