微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

检索 UserInfo 的访问令牌

如何解决检索 UserInfo 的访问令牌

我希望能够访问 UserInfo 端点 /connect/userinfo,但是当我这样做时,它显示 401... 暗示需要身份验证。所以我遇到了这篇文章,它讨论了我们如何在 .net 代码中实现它以便能够访问 UserInfo Endpoint。因此,在我的 TokenServices.cs 文件中,我执行了以下操作,但我不确定如何获取令牌本身。 我确实有一个方法 GetToken() 可以检索令牌,但我不确定是否可以将该方法用于设置 Token = token 的行。

public async Task<TokenResponse> GetUserInfoToken(string scope)
        {
            using var client = new HttpClient();
           
            var tokenResponse = await client.GetUserInfoAsync(new UserInfoRequest
            {
                Address = _discoveryDocument.UserInfoEndpoint,//      Token = token
            });

            if (tokenResponse.isError)
            {
                _logger.LogError($"Unable to get userinfo token. Error is: {tokenResponse.Error}");
                throw new Exception("Unable to get UserInfo token",tokenResponse.Exception);
            }
            return tokenResponse;
        }

这是完整的类文件

namespace WeatherMVC.Services
{
    public class TokenService : ITokenService
    {
        private readonly ILogger<TokenService> _logger;
        private readonly IOptions<IdentityServerSettings> _identityServerSettings;
        private readonly discoveryDocumentResponse _discoveryDocument;

        public TokenService(ILogger<TokenService> logger,IOptions<IdentityServerSettings> identityServerSettings)
        {
            _logger = logger;
            _identityServerSettings = identityServerSettings;

            using var httpClient = new HttpClient();
            _discoveryDocument = httpClient.GetdiscoveryDocumentAsync(identityServerSettings.Value.discoveryUrl).Result;

            if (_discoveryDocument.IsError)
            {
                logger.LogError($"Unable to get discovery document. Error is: {_discoveryDocument.Error}");
                throw new Exception("Unable to get discovery document",_discoveryDocument.Exception);
            }
        }

        public async Task<TokenResponse> GetToken(string scope)
        {
            using var client = new HttpClient();
            var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = _discoveryDocument.TokenEndpoint,ClientId = _identityServerSettings.Value.ClientName,ClientSecret = _identityServerSettings.Value.ClientPassword,Scope = scope
            });

            if (tokenResponse.IsError)
            {
                _logger.LogError($"Unable to get token. Error is: {tokenResponse.Error}");
                throw new Exception("Unable to get token",tokenResponse.Exception);
            }
            return tokenResponse;
        }

        public async Task<TokenResponse> GetUserInfoToken(string scope)
        {
            using var client = new HttpClient();
           
            var tokenResponse = await client.GetUserInfoAsync(new UserInfoRequest
            {
                Address = _discoveryDocument.UserInfoEndpoint,tokenResponse.Exception);
            }
            return tokenResponse;
        }
    }

在我的 HomeController 中,我有

namespace WeatherMVC.Controllers
{
    public class HomeController : Controller
    {
        private readonly ITokenService _tokenService;
        private readonly ILogger<HomeController> _logger;

        public HomeController(ITokenService tokenService,ILogger<HomeController> logger)
        {
            _tokenService = tokenService;
            _logger = logger;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [Authorize] // 25:44 in youtube video
        public async Task<IActionResult> Weather()
        {
            var data = new List<WeatherData>();
            
            using (var client = new HttpClient())
            {
                var tokenResponse = await _tokenService.GetToken("weatherapi.read");

                client.SetBearerToken(tokenResponse.Accesstoken);

                var result = client
                    .GetAsync("https://localhost:5445/weatherforecast")
                    .Result;

                if (result.IsSuccessstatusCode)
                {
                    var model = result.Content.ReadAsstringAsync().Result;

                    data = JsonConvert.DeserializeObject<List<WeatherData>>(model);

                    return View(data);
                }
                else
                {
                    throw new Exception("Unable to get content");
                }
            }
        }

        [responsecache(Duration = 0,Location = responsecacheLocation.None,NoStore = true)]
        public IActionResult Error()
        {
            return View(new Errorviewmodel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }

Startup.cs

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

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "cookie";
                options.DefaultChallengeScheme = "oidc";
            })
                .AddCookie("cookie")
                .AddOpenIdConnect("oidc",options =>
                {
                    options.Authority = Configuration["InteractiveServiceSettings:AuthorityUrl"];
                    options.ClientId = Configuration["InteractiveServiceSettings:ClientId"];
                    options.ClientSecret = Configuration["InteractiveServiceSettings:ClientSecret"];

                    options.ResponseType = "code";
                    options.UsePkce = true;
                    options.ResponseMode = "query";

                    options.Scope.Add(Configuration["InteractiveServiceSettings:Scopes:0"]);
                    options.Savetokens = true;

                });


            services.Configure<IdentityServerSettings>(Configuration.GetSection("IdentityServerSettings"));
            services.AddSingleton<ITokenService,TokenService>();
        }

WeatherApi Project

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {

            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication("Bearer",options =>
                {
                    options.ApiName = "weatherapi";
                    options.Authority = "https://localhost:5443";
                });

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1",new OpenApiInfo { Title = "weatherapi",Version = "v1" });
            });
        }

Identity project

namespace identity
{
    public static class Config
    {
        public static List<TestUser> Users
        {
            get
            {
                var address = new
                {
                    street_address = "One Hacker Way",locality = "Heidelberg",postal_code = 69118,country = "Germany"
                };

                return new List<TestUser>
        {
          new TestUser
          {
            SubjectId = "818727",Username = "alice",Password = "alice",Claims =
            {
              new Claim(JwtClaimTypes.Name,"Alice Smith"),new Claim(JwtClaimTypes.Givenname,"Alice"),new Claim(JwtClaimTypes.FamilyName,"Smith"),new Claim(JwtClaimTypes.Email,"AliceSmith@email.com"),new Claim(JwtClaimTypes.EmailVerified,"true",ClaimValueTypes.Boolean),new Claim(JwtClaimTypes.Role,"admin"),new Claim(JwtClaimTypes.WebSite,"http://alice.com"),new Claim(JwtClaimTypes.Address,JsonSerializer.Serialize(address),IdentityServerConstants.ClaimValueTypes.Json)
            }
          },new TestUser
          {
            SubjectId = "88421113",Username = "bob",Password = "bob","Bob Smith"),"Bob"),"BobSmith@email.com"),"user"),"http://bob.com"),IdentityServerConstants.ClaimValueTypes.Json)
            }
          }
        };
            }
        }

        public static IEnumerable<IdentityResource> IdentityResources =>
          new[]
          {
        new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResource
        {
          Name = "role",UserClaims = new List<string> {"role"}
        }
          };

        public static IEnumerable<ApiScope> ApiScopes =>
          new[]
          {
        new ApiScope("weatherapi.read"),new ApiScope("weatherapi.write"),};
        public static IEnumerable<ApiResource> ApiResources => new[]
        {
      new ApiResource("weatherapi")
      {
        Scopes = new List<string> {"weatherapi.read","weatherapi.write"},ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},UserClaims = new List<string> {"role"}
      }
    };

        public static IEnumerable<Client> Clients =>
          new[]
          {
        // m2m client credentials flow client
        new Client
        {
          ClientId = "m2m.client",ClientName = "Client Credentials Client",AllowedGrantTypes = GrantTypes.ClientCredentials,ClientSecrets = {new Secret("SuperSecretPassword".Sha256())},AllowedScopes = {"weatherapi.read","weatherapi.write"}
        },// interactive client using code flow + pkce
        new Client
        {
          ClientId = "interactive",AllowedGrantTypes = GrantTypes.Code,RedirectUris = {"https://localhost:5444/signin-oidc","https://localhost:44394/signin-oidc"},FrontChannellogoutUri = "https://localhost:5444/signout-oidc",PostlogoutRedirectUris = {"https://localhost:5444/signout-callback-oidc"},AllowOfflineAccess = true,AllowedScopes = {"openid","profile","weatherapi.read"},RequirePkce = true,RequireConsent = true,AllowPlainTextPkce = false
        },};
    }
}

是否有一种特定的方式可以调用令牌,以便将 Token 设置为该 UserInfo 令牌?任何指针/建议将不胜感激!


更新

enter image description here

enter image description here

enter image description here

要访问此屏幕 (HomeController -> Weather()),我必须获得授权,并且在我访问此页面时它会让我保持登录状态,无论不记名令牌显示其持续多长时间。那么为什么我无法访问 /connect/userinfo 页面

enter image description here

解决方法

options.SaveTokens = true 的使用; (在 AddOpenIDConnect 中)将所有令牌保存在用户 cookie 中,然后您可以使用:

var accessToken = await HttpContext.GetTokenAsync("access_token");

Sample code to get all the tokens if provided:

            ViewBag.access_token = HttpContext.GetTokenAsync("access_token").Result;
            ViewBag.id_token = HttpContext.GetTokenAsync("id_token").Result;
            ViewBag.refresh_token = HttpContext.GetTokenAsync("refresh_token").Result;
            ViewBag.token_type = HttpContext.GetTokenAsync("token_type").Result;    //Bearer
            ViewBag.expires_at = HttpContext.GetTokenAsync("expires_at").Result;    // "2021-02-01T10:58:28.0000000+00:00"

发出请求的示例代码

var accessToken = await HttpContext.GetTokenAsync("access_token");

var authheader = new AuthenticationHeaderValue("Bearer",accessToken);


var client = new HttpClient();


var authheader = new AuthenticationHeaderValue("Bearer",accessToken);
client.DefaultRequestHeaders.Authorization = authheader;

var content = await client.GetStringAsync("https://localhost:7001/api/payment");

ViewBag.Json = JObject.Parse(content).ToString();
return View();

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。