05 Resource Owner Password Credentials 授权


原文:https://www.yuque.com/yuejiangliu/dotnet/qq7lgs


05 Resource Owner Password Credentials 授权.mp4 (93.5 MB)

jwt.io 解码查看:

image.png

二、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;
        }

        // request access token
        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)
    {
        // call API1 Resource
        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)
    {
        // call Identity Resource from Identity Server
        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 Values

  • profile
  • OPTIONAL. This scope 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.
  • email
  • OPTIONAL. This scope value requests access to the email and email_verified Claims.
  • address
  • OPTIONAL. This scope value requests access to the address Claim.
  • phone
  • 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 相比:

  1. 多了用户角色
  2. 可以访问身份认证信息

image.png

相关