首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法将Okta授权代码交换为令牌的Xamarin必需程序

无法将Okta授权代码交换为令牌的Xamarin必需程序
EN

Stack Overflow用户
提问于 2020-12-01 18:54:22
回答 1查看 185关注 0票数 2

我正在使用OpenID,我们必须切换到Xamarin.Essentials.WebAuthenticator。

我可以使用WebAuthenticator.AuthenticateAsync()从Okta获得授权代码。

但是,我试图将该代码转换为访问令牌的所有内容都会返回400坏请求。

Okta的API错误是"E0000021: HTTP媒体类型不支持的异常“,它接着说,”糟糕的请求。接受和/或内容类型标题可能与支持的值不匹配。“

我已经尝试了尽可能多的跟随https://developer.okta.com/blog/2020/07/31/xamarin-essentials-webauthenticator,但是我们没有像他那样使用混合赠款类型。

我们只使用授权代码,这意味着我必须打第二次电话,我花了两天时间试图弄清楚怎么做。

代码语言:javascript
复制
private async Task LoginOktaAsync()
{
  try
  {
    var loginUrl = new Uri(BuildAuthenticationUrl());  // that method is down below
    var callbackUrl = new Uri("com.oktapreview.dev-999999:/callback"); // it's not really 999999
    var authenticationResult = await Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(loginUrl, callbackUrl);

    string authCode;                                
    authenticationResult.Properties.TryGetValue("code",out authCode);

    // Everything works fine up to this point. I get the authorization code.

    var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/token"
         +"?grant_type=authorization_code"
         +$"&code={authCode}&client_id={OktaConfiguration.ClientId}&code_verifier={codeVerifier}";

    var request = new HttpRequestMessage(HttpMethod.Post, url);
    var client = new HttpClient();
    var response = await client.SendAsync(request); // this generates the 400 error.
  }
  catch(Exception e)
  {
    Debug.WriteLine($"Error: {e.Message}");
  }
}

下面是生成登录url和其他一些东西的方法:

代码语言:javascript
复制
public string BuildAuthenticationUrl()
{
  var state = CreateCryptoGuid();
  var nonce = CreateCryptoGuid();

  CreateCodeChallenge();

  var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/authorize?response_type=code"
      + "&response_mode=fragment"
      + "&scope=openid%20profile%20email"
      + "&redirect_uri=com.oktapreview.dev-999999:/callback"
      +$"&client_id={OktaConfiguration.ClientId}"
      +$"&state={state}"
      +$"&code_challenge={codeChallenge}"
      + "&code_challenge_method=S256"
      +$"&nonce={nonce}";
  return url;
}

private string CreateCryptoGuid()
{
  using (var generator = RandomNumberGenerator.Create())
  {
    var bytes = new byte[16];
    generator.GetBytes(bytes);
    return new Guid(bytes).ToString("N");
  }
}

private string CreateCodeChallenge()
{
  codeChallenge = GenerateCodeToVerify();
  codeVerifier = codeChallenge;
  using (var sha256 = SHA256.Create())
  {
    var codeChallengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeChallenge));
    return Convert.ToBase64String(codeChallengeBytes);
  }
}    

private string GenerateCodeToVerify() 
{
  var str = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
  Random rnd = new Random();
  for (var i = 0; i < 100; i++) 
  {
    str += possible.Substring(rnd.Next(0,possible.Length-1),1);
  }
  return str;
}


'''
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-03 15:02:23

经过大量的在线研究后,我发现问题在于我是如何做我的帖子来获得标记的。我就是这样做的:

代码语言:javascript
复制
public static Dictionary<string, string> JsonDecode(string encodedString)
{
    var inputs = new Dictionary<string, string>();
    var json = JValue.Parse(encodedString) as JObject;

    foreach (KeyValuePair<string, JToken> kv in json)
    {
        if (kv.Value is JValue v)
        {
            if (v.Type != JTokenType.String)
                inputs[kv.Key] = v.ToString();
            else
                inputs[kv.Key] = (string)v;
        }
    }
    return inputs;
}


private async Task<string> ExchangeAuthCodeForToken(string authCode)
{
    string accessToken = string.Empty;
    List<KeyValuePair<string, string>> kvdata = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("grant_type", "authorization_code"),
        new KeyValuePair<string, string>("code", authCode),
        new KeyValuePair<string, string>("redirect_uri", OktaConfiguration.Callback),
        new KeyValuePair<string, string>("client_id", OktaConfiguration.ClientId),
        new KeyValuePair<string, string>("code_verifier", codeVerifier)
    };
    var content = new FormUrlEncodedContent(kvdata);

    var request = new HttpRequestMessage(HttpMethod.Post, OktaConfiguration.TokenUrl)
                {Content = content, Method = HttpMethod.Post};
    HttpClient client = new HttpClient();
    HttpResponseMessage response = await client.SendAsync(request);
    string text = await response.Content.ReadAsStringAsync();
    Dictionary<string, string> data = JsonDecode(text);
    data.TryGetValue("access_token", out accessToken);
    return accessToken;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65096766

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档