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

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

我已经实现了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枚举。以下是我的客户端配置:
new Client
            {
                ClientId = "client",
                ClientSecrets = { new Secret("secret".Sha256()) },

                //RequireClientSecret = false, //false is default

                RequirePkce = false, //to prevent 'code challenge required' message from appearing when using 'Code'

                AllowedGrantTypes = GrantTypes.Code ,//{ "code", "authorization_code" },// 

                // where to redirect to after login
                RedirectUris = { "https://IDS4.azurewebsites.net/signin-oidc", "https://test.azurewebsites.net/auth",
                "https://test.azurewebsites.net/token", "https://IDS4.azurewebsites.net/Account/Login"  },

                // where to redirect to after logout
                PostLogoutRedirectUris = { "https://IDS4.azurewebsites.net/signout-callback-oidc" },

                AllowedScopes = new List<string>
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,   
                    "myAPI"
                }
            }

我的启动代码:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        services.AddDbContextPool<AppDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DBConnection")));

        var builder = services.AddIdentityServer()
            .AddInMemoryIdentityResources(Config.IdentityResources)
            .AddInMemoryApiScopes(Config.ApiScopes)
            .AddInMemoryClients(Config.Clients)
            .AddTestUsers(TestUsers.Users)
            .AddCustomTokenRequestValidator<CustomTokenRequestValidator>()
            .AddCustomAuthorizeRequestValidator<CustomAuthorizeRequestValidator>();

        builder.AddDeveloperSigningCredential();

        services.AddAuthentication()
            .AddGoogle("Google", options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                options.ClientId = "<insert here>";
                options.ClientSecret = "<insert here>";
            });

        services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddXmlSerializerFormatters()
            .AddMvcOptions(options => options.EnableEndpointRouting = false);

        services.AddScoped<IDebugRepository, SQLDebugRepository>();
        services.AddScoped<IPatientContextRepository, SQLPatientContextRepository>();
        services.AddScoped<IClinicAccessRepository, SQLClinicAccessRepository>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCookiePolicy(new CookiePolicyOptions
        {
            HttpOnly = HttpOnlyPolicy.None,
            MinimumSameSitePolicy = SameSiteMode.None,
            Secure = CookieSecurePolicy.Always
        });

        app.UseStaticFiles();
        app.UseRouting();

        app.UseIdentityServer();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });

    }

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

[HttpGet]
        public async Task<string> Get(string code, string scope, string state, string session_state)
        {

        try
        {
            //AuthResponseModel arm = new AuthResponseModel
            //{
            //    code = code,
            //    scope = scope,
            //    state = state,
            //    session_state = session_state
            //};

            string grant_type = "authorization_code";
            string redirect_uri = "https://test.azurewebsites.net/token"; //sends the token back to requestor
            string client_id = "client"; //current stable testing client
            string baseAddress = $"https://IDS4.azurewebsites.net/connect/token";
            string client_secret = "secret";

            var client = new HttpClient();
            client.BaseAddress = new Uri($"https://IDS4.azurewebsites.net/");
            var content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("client_id", client_id),
                new KeyValuePair<string, string>("client_secret", client_secret),
                new KeyValuePair<string, string>("grant_type", grant_type),
                new KeyValuePair<string, string>("code", code),
                new KeyValuePair<string, string>("redirect_uri", redirect_uri)
              });

            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));

            var res = await client.PostAsync(baseAddress, content);
            var resp = await res.Content.ReadAsStringAsync();
            return resp;

        }
        catch (Exception ex)
        {
            return  ex.Message + Environment.NewLine + ex.StackTrace ;
        }
    }

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

[Controller]
[Route("Token")]
[AllowAnonymous]
public class TokenController : Controller
{

    [HttpPost]
    public string Post([FromForm] string access_token,
                        [FromForm] string token_type,
                        [FromForm] string expires_in,
                        [FromForm] string scope,
                        [FromForm] string patient,
                        [FromForm] string id_token,
                        [FromForm] string oceanSharedEncryptionKey)
    {
        TokenResponseModel token = new TokenResponseModel
        {
            access_token = access_token,
            expires_in = expires_in,
            id_token = id_token,
            patient = patient,
            scope = scope,
            token_type = token_type
        };
        string rslt = JsonConvert.SerializeObject(token);
        return rslt;
    }

    public string Get( string test1)
    {
        return test1;
    }
}
mrzz3bfm

mrzz3bfm1#

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

private async Task<string> GetNewAccessTokenAsync()
        {
            var postMessage = new Dictionary<string, string>
        {
                {"client_id", "Client ID goes here"},
                {"client_secret","Client secret goes here" },
                {"scope","User.Read" },

                {"grant_type", "password"},
                {"username", "Username goes here"},
                {"password", "Password goes here"}

        };

            var client1 = new HttpClient();
            var response = await client1.PostAsync("https://login.microsoftonline.com/{{id}}/oauth2/v2.0/token", new FormUrlEncodedContent(postMessage));

            // return response.ReasonPhrase;
            if (response.IsSuccessStatusCode)
            {
                var json = response.Content.ReadAsStringAsync();

                return json.Result;
            }
            return "";

        }

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

相关问题