原文:https://www.yuque.com/yuejiangliu/dotnet/qq7lgs
05 Resource Owner Password Credentials 授权.mp4
(93.5 MB)
jwt.io 解码查看:
二、MainWindow 代码:
public partial class MainWindow : Window
{
private string _accessToken ;
private DiscoveryResponse _disco ;
public MainWindow ()
{
InitializeComponent ();
}
private async void RequestAccessToken_ButtonClick (object sender , RoutedEventArgs e )
{
var userName = UserNameInput .Text ;
var password = PasswordInput .Password ;
var client = new HttpClient ();
var disco = await client .GetDiscoveryDocumentAsync ("http://localhost:5000/" );
_disco = disco ;
if (disco .IsError )
{
Console .WriteLine (disco .Error );
return ;
}
var tokenResponse = await client .RequestPasswordTokenAsync (new PasswordTokenRequest
{
Address = disco .TokenEndpoint ,
ClientId = "wpf client" ,
ClientSecret = "wpf secret" ,
Scope = "api1 openid profile address phone email" ,
UserName = userName ,
Password = password
});
if (tokenResponse .IsError )
{
MessageBox .Show (tokenResponse .Error );
return ;
}
_accessToken = tokenResponse .AccessToken ;
AccessTokenTextBlock .Text = tokenResponse .Json .ToString ();
}
private async void RequestApi1Resource_ButtonClick (object sender , RoutedEventArgs e )
{
var apiClient = new HttpClient ();
apiClient .SetBearerToken (_accessToken );
var response = await apiClient .GetAsync ("http://localhost:5001/identity" );
if (! response .IsSuccessStatusCode )
{
MessageBox .Show (response .StatusCode .ToString ());
}
else
{
var content = await response .Content .ReadAsStringAsync ();
Api1ResponseTextBlock .Text = content ;
}
}
private async void RequestIdentityResource_ButtonClick (object sender , RoutedEventArgs e )
{
var apiClient = new HttpClient ();
apiClient .SetBearerToken (_accessToken );
var response = await apiClient .GetAsync (_disco .UserInfoEndpoint );
if (! response .IsSuccessStatusCode )
{
MessageBox .Show (response .StatusCode .ToString ());
}
else
{
var content = await response .Content .ReadAsStringAsync ();
IdentityResponseTextBlock .Text = content ;
}
}
}
5.4. Requesting Claims using Scope ValuesOPTIONAL. This s cope value requests access to the End-User's default profile Claims, which are: name, family_name, given_name, middle_name, nickname, preferred_username, profile, picture, website, gender, birthdate, zoneinfo, locale
, and updated_at
. OPTIONAL. This scope value requests access to the email
and email_verified
Claims. OPTIONAL. This scope value requests access to the address
Claim. OPTIONAL. This scope value requests access to the phone_number
and phone_number_verified
Claims. 4、 Token 请求与响应 Token 请求:
POST /oauth/token HTTP/1.1
Host: authorization-server.com
grant_type=password
&username=user@example.com
&password=xxx
&client_id=xxx
&client_secret=xxx
响应:
{
"access_token'; "MTQONjOkZmQ5OTM5NDE9ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
}
5、 示意图 和 Client Credentials 相比:
多了用户角色 可以访问身份认证信息