oauth-2.0 为什么在Postman中可以获得我的访问令牌,而在我的代码中却不行?

ryevplcw  于 2022-10-31  发布在  Postman
关注(0)|答案(1)|浏览(389)

我已经实现了Identity Server 4来进行OAuth身份验证,当我在Postman中发出身份验证请求时,它工作正常(我收到了AccessToken、Token Type、id_token、expires_in等),并且可以使用访问令牌来访问我的受保护API。但是,当我尝试在代码中执行此操作时,我以错误“invalid_grant”结束。
为什么在Postman中可以工作,但在代码中调用时却不行?
我的过程如下:
1.通过将患者ID和GUID保存到数据库,进行API调用以设置患者上下文。GUID是我的“启动”值。
1.我调用了一个自定义/auth端点,因为它需要额外的参数(“启动”),用于维护上下文(患者的id值),传入ID 4/connect/authorize/的所有必需参数。
例如,https://IDS4.azurewebsites.net/auth2?client_id=client&response_type=code&scope=openid配置文件myAPI和客户端密码=密码和状态= 1234567890api.location.comtest.azurewebsites.net/auth
此端点会将'state'的值与数据库中的'launch'相关联,以维护上下文。
1.上面的端点然后调用IDS 4/connect/authorize/ endpoint,传入适当的值。在auth管道中,我然后再次将“sessionId”与“state”关联以维护上下文。

  1. IDS 4/connect/authorize/ endpoint会如预期般传回受权码、范围、状态和session_state。
    1.在上面的'authorize'调用中指定的redirectURI的Get中,我获取授权代码并执行到ID 4/connect/token端点的标准post。
    1.响应为“invalid_grant”
    所有这些在Postman中都适用。
    我已经尝试更改我的客户端的AllowedGrantTypes,但我认为“authorization_code”是一个可以坚持的。我使用GrantTypes枚举。以下是我的客户端配置:
  1. new Client
  2. {
  3. ClientId = "client",
  4. ClientSecrets = { new Secret("secret".Sha256()) },
  5. //RequireClientSecret = false, //false is default
  6. RequirePkce = false, //to prevent 'code challenge required' message from appearing when using 'Code'
  7. AllowedGrantTypes = GrantTypes.Code ,//{ "code", "authorization_code" },//
  8. // where to redirect to after login
  9. RedirectUris = { "https://IDS4.azurewebsites.net/signin-oidc", "https://test.azurewebsites.net/auth",
  10. "https://test.azurewebsites.net/token", "https://IDS4.azurewebsites.net/Account/Login" },
  11. // where to redirect to after logout
  12. PostLogoutRedirectUris = { "https://IDS4.azurewebsites.net/signout-callback-oidc" },
  13. AllowedScopes = new List<string>
  14. {
  15. IdentityServerConstants.StandardScopes.OpenId,
  16. IdentityServerConstants.StandardScopes.Profile,
  17. "myAPI"
  18. }
  19. }

我的启动代码:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllersWithViews();
  4. services.AddDbContextPool<AppDbContext>(options =>
  5. options.UseSqlServer(Configuration.GetConnectionString("DBConnection")));
  6. var builder = services.AddIdentityServer()
  7. .AddInMemoryIdentityResources(Config.IdentityResources)
  8. .AddInMemoryApiScopes(Config.ApiScopes)
  9. .AddInMemoryClients(Config.Clients)
  10. .AddTestUsers(TestUsers.Users)
  11. .AddCustomTokenRequestValidator<CustomTokenRequestValidator>()
  12. .AddCustomAuthorizeRequestValidator<CustomAuthorizeRequestValidator>();
  13. builder.AddDeveloperSigningCredential();
  14. services.AddAuthentication()
  15. .AddGoogle("Google", options =>
  16. {
  17. options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
  18. options.ClientId = "<insert here>";
  19. options.ClientSecret = "<insert here>";
  20. });
  21. services.AddMvc()
  22. .SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddXmlSerializerFormatters()
  23. .AddMvcOptions(options => options.EnableEndpointRouting = false);
  24. services.AddScoped<IDebugRepository, SQLDebugRepository>();
  25. services.AddScoped<IPatientContextRepository, SQLPatientContextRepository>();
  26. services.AddScoped<IClinicAccessRepository, SQLClinicAccessRepository>();
  27. }
  28. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  29. {
  30. if (env.IsDevelopment())
  31. {
  32. app.UseDeveloperExceptionPage();
  33. }
  34. app.UseCookiePolicy(new CookiePolicyOptions
  35. {
  36. HttpOnly = HttpOnlyPolicy.None,
  37. MinimumSameSitePolicy = SameSiteMode.None,
  38. Secure = CookieSecurePolicy.Always
  39. });
  40. app.UseStaticFiles();
  41. app.UseRouting();
  42. app.UseIdentityServer();
  43. app.UseAuthorization();
  44. app.UseEndpoints(endpoints =>
  45. {
  46. endpoints.MapDefaultControllerRoute();
  47. });
  48. }

这就是我如何在Auth Get中对/connect/Token端点执行POST:

  1. [HttpGet]
  2. public async Task<string> Get(string code, string scope, string state, string session_state)
  3. {
  4. try
  5. {
  6. //AuthResponseModel arm = new AuthResponseModel
  7. //{
  8. // code = code,
  9. // scope = scope,
  10. // state = state,
  11. // session_state = session_state
  12. //};
  13. string grant_type = "authorization_code";
  14. string redirect_uri = "https://test.azurewebsites.net/token"; //sends the token back to requestor
  15. string client_id = "client"; //current stable testing client
  16. string baseAddress = $"https://IDS4.azurewebsites.net/connect/token";
  17. string client_secret = "secret";
  18. var client = new HttpClient();
  19. client.BaseAddress = new Uri($"https://IDS4.azurewebsites.net/");
  20. var content = new FormUrlEncodedContent(new[]
  21. {
  22. new KeyValuePair<string, string>("client_id", client_id),
  23. new KeyValuePair<string, string>("client_secret", client_secret),
  24. new KeyValuePair<string, string>("grant_type", grant_type),
  25. new KeyValuePair<string, string>("code", code),
  26. new KeyValuePair<string, string>("redirect_uri", redirect_uri)
  27. });
  28. client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
  29. var res = await client.PostAsync(baseAddress, content);
  30. var resp = await res.Content.ReadAsStringAsync();
  31. return resp;
  32. }
  33. catch (Exception ex)
  34. {
  35. return ex.Message + Environment.NewLine + ex.StackTrace ;
  36. }
  37. }

有一件事我还没有尝试设置一个签名证书。我想 Postman 使用一个内部证书,我需要接受,但它是如此之久,我不太记得如果我这样做或没有。我会认为,一个失踪的证书会给我带来问题之前,现在,但它是我正在调查的事情。
此外,只是一个说明-我已经测试了令牌重定向,它是工作的。
这是:

  1. [Controller]
  2. [Route("Token")]
  3. [AllowAnonymous]
  4. public class TokenController : Controller
  5. {
  6. [HttpPost]
  7. public string Post([FromForm] string access_token,
  8. [FromForm] string token_type,
  9. [FromForm] string expires_in,
  10. [FromForm] string scope,
  11. [FromForm] string patient,
  12. [FromForm] string id_token,
  13. [FromForm] string oceanSharedEncryptionKey)
  14. {
  15. TokenResponseModel token = new TokenResponseModel
  16. {
  17. access_token = access_token,
  18. expires_in = expires_in,
  19. id_token = id_token,
  20. patient = patient,
  21. scope = scope,
  22. token_type = token_type
  23. };
  24. string rslt = JsonConvert.SerializeObject(token);
  25. return rslt;
  26. }
  27. public string Get( string test1)
  28. {
  29. return test1;
  30. }
  31. }
mrzz3bfm

mrzz3bfm1#

您需要提供授权类型。您可以在此处找到案例的文档-https://docs.identityserver.io/en/latest/topics/grant_types.html
我有一个类似的实现,我在postman中使用客户端凭据,在代码中使用密码。

  1. private async Task<string> GetNewAccessTokenAsync()
  2. {
  3. var postMessage = new Dictionary<string, string>
  4. {
  5. {"client_id", "Client ID goes here"},
  6. {"client_secret","Client secret goes here" },
  7. {"scope","User.Read" },
  8. {"grant_type", "password"},
  9. {"username", "Username goes here"},
  10. {"password", "Password goes here"}
  11. };
  12. var client1 = new HttpClient();
  13. var response = await client1.PostAsync("https://login.microsoftonline.com/{{id}}/oauth2/v2.0/token", new FormUrlEncodedContent(postMessage));
  14. // return response.ReasonPhrase;
  15. if (response.IsSuccessStatusCode)
  16. {
  17. var json = response.Content.ReadAsStringAsync();
  18. return json.Result;
  19. }
  20. return "";
  21. }

如果对你有用,请在答案上做记号。

展开查看全部

相关问题