Xamarin Mobile与IdentityServer 3

时间:2018-07-23 14:58:16

标签: xamarin identityserver3 bearer-token

我正在尝试使用身份服务器3和Xamarin为我的移动应用程序建立安全连接。我有一个网络应用程序,可以很好地使用身份服务器运行,但是我一生都无法在移动设备上使用它。我要求输入凭据,登录并获取访问令牌。但是,当我尝试使用令牌进行呼叫时,我仍然将HttpContext.User.Identity.IsAuthenticated设置为false,并且呼叫失败。

我在身份服务器中为移动应用创建了一个新客户端,并将其设置如下:

new IdentityServer3.Core.Models.Client
{
  Enabled = true,
  ClientName = "MyMobile Mobile App",
  ClientId = "myMobile",
  ClientSecrets = { new Secret("myMobileSecret".Sha256()) },
  Flow = Flows.Hybrid,
  RedirectUris = new List<string>
  {
    …
  },
  PostLogoutRedirectUris = new List<string>
  {
    …
  },
  RequireConsent = false,
  AllowAccessToAllScopes = true,
  RequireSignOutPrompt = false
}

我的代码如下:

var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);

var dic = new Dictionary<string, string>();
dic.Add("client_id", GlobalSetting.Instance.ClientId);
dic.Add("client_secret", GlobalSetting.Instance.ClientSecret);
dic.Add("response_type", "code token");
dic.Add("scope", "openid profile roles");
dic.Add("redirect_uri", GlobalSetting.Instance.IdentityCallback);
dic.Add("nonce", Guid.NewGuid().ToString("N"));

_currentCSRFToken = Guid.NewGuid().ToString("N");
dic.Add("state", _currentCSRFToken);

var authorizeUri = authorizeRequest.Create(dic);           
LoginWebView.Source = authorizeUri;

在响应中……

private async Task NavigateAsync(string url)
{
  var unescapedUrl = System.Net.WebUtility.UrlDecode(url);

  if (unescapedUrl.StartsWith(GlobalSetting.Instance.IdentityCallback))
  {
      LoginWebView.IsVisible = false;

      var authResponse = new AuthorizeResponse(url);
      if (!string.IsNullOrWhiteSpace(authResponse.Code))
      {
          var userToken = await _identityService.GetTokenAsync(authResponse.Code);

          string accessToken = userToken.AccessToken;
          if (!string.IsNullOrWhiteSpace(accessToken))
          {
              Authorization.AccessToken = accessToken;
              Authorization.IdToken = authResponse.IdentityToken;

              Application.Current.MainPage = _homePage;
          }
      }
  }
  …
}

public async Task<UserToken> GetTokenAsync(string code)
{
  string data = string.Format("grant_type=authorization_code&code={0}&redirect_uri={1}&code_verifier={2}", code, WebUtility.UrlEncode(GlobalSetting.Instance.IdentityCallback), _codeVerifier);
  var token = await _requestProvider.PostAsync<UserToken> (GlobalSetting.Instance.TokenEndpoint, data, GlobalSetting.Instance.ClientId, GlobalSetting.Instance.ClientSecret);
  return token;
}

然后当我打电话时...

RestClient rest = new RestClient(GlobalSetting.DefaultBaseUrl);

var request = new RestRequest("Partner/GetMyItem", Method.POST);
request.AddParameter("detail", MyEnumValue.ToString());

//tried both of the following…
request.AddParameter("Authorization", string.Format("Bearer {0}", Authorization.AccessToken), ParameterType.HttpHeader);
rest.AddDefaultHeader("Authorization", string.Format("Bearer {0}", Authorization.AccessToken));

IRestResponse res = rest.Post(request);

功能…

[HttpPost]
[ValidateInput(false)]
[AuthAttribute(Roles = …)]
[HandleForbidden]
public string GetMyItem(MyEnum detail)

在服务器身份日志中,我有以下内容…

2018-07-23 14:03:11.508 +00:00 [Information] Start authorize request
2018-07-23 14:03:11.508 +00:00 [Information] Start authorize request protocol validation
2018-07-23 14:03:11.508 +00:00 [Information] "Authorize request validation success"
 "{
  \"ClientId\": \"myMobile\",
  \"ClientName\": \"myMobile App\",
  \"RedirectUri\": \"https://localhost:44000/\",
  \"AllowedRedirectUris\": [
    \"https://localhost:44000/\",
      ...
  ],
  \"SubjectId\": \"unknown\",
  \"ResponseType\": \"code token\",
  \"ResponseMode\": \"fragment\",
  \"Flow\": \"Hybrid\",
  \"RequestedScopes\": \"openid profile roles\",
  \"State\": \"a971d692ae8f424493966023f5934b70\",
  \"Nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
  \"Raw\": {
    \"client_id\": \"myMobile\",
    \"client_secret\": \"myMobileSecret\",
    \"response_type\": \"code token\",
    \"scope\": \"openid profile roles\",
    \"redirect_uri\": \"https://localhost:44000/\",
    \"nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
    \"state\": \"a971d692ae8f424493966023f5934b70\"
  }
}"
2018-07-23 14:03:11.524 +00:00 [Information] User is not authenticated. Redirecting to login.
2018-07-23 14:03:11.524 +00:00 [Information] End authorize request
2018-07-23 14:03:11.524 +00:00 [Information] Redirecting to login page
2018-07-23 14:03:11.524 +00:00 [Debug] Protecting message: "{\"ReturnUrl\":\"https://....net/identity/connect/authorize?client_id=myMobile&client_secret=myMobileSecret&response_type=code%20token&scope=openid%20profile%20roles&redirect_uri=https%3A%2F%2Flocalhost%3A44000%    2F&nonce=ec42d50463cc418dacbd04f1c43873d0&state=a971d692ae8f424493966023f5934b70\",\"ClientId\":\"myMobile\",\"AcrValues\":[],\"Created\":636679513915083066}"
2018-07-23 14:03:11.570 +00:00 [Information] Login page requested
2018-07-23 14:03:11.570 +00:00 [Debug] signin message passed to login: "{
  \"ReturnUrl\": \"https://...net/identity/connect/authorize?client_id=myMobile&client_secret=myMobileSecret&response_type=code%20token&scope=openid%20profile%20roles&redirect_uri=https%3A%2F%2Flocalhost%3A44000%    2F&nonce=ec42d50463cc418dacbd04f1c43873d0&state=a971d692ae8f424493966023f5934b70\",
  \"ClientId\": \"myMobile\",
  \"IdP\": null,
  \"Tenant\": null,
  \"LoginHint\": null,
  \"DisplayMode\": null,
  \"UiLocales\": null,
  \"AcrValues\": [],
  \"Created\": 636679513915083066
}"
2018-07-23 14:03:11.570 +00:00 [Information] rendering login page
2018-07-23 14:03:12.007 +00:00 [Information] CSP Report endpoint requested
2018-07-23 14:03:12.007 +00:00 [Information] CSP Report data: "{\"csp-report\":{\"document-uri\":\"https://...net/identity/login?signin=df9bdfc781a634b806ecc6555e9989ca\",\"referrer\":\"\",\"blocked-uri\":\"\",\"violated-directive\":\"script-src 'self'\",\"original-policy\":\"default-src 'self'; script-src 'self' ;     style-src 'self' 'unsafe-inline' style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src *; font-src font-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; report-uri https://devs3server.azurewebsites.net/identity/csp/report\",\"effective-directive\":\"script-src\",\"status-code\":200,\"source-    file\":\"https://devs3server.azurewebsites.net/identity/login?signin=df9bdfc781a634b806ecc6555f9989ca\"}}"
2018-07-23 14:03:12.007 +00:00 [Information] Rendering 204
2018-07-23 14:03:26.772 +00:00 [Information] Login page submitted
2018-07-23 14:03:26.803 +00:00 [Information] Login credentials successfully validated by user service
2018-07-23 14:03:26.803 +00:00 [Information] Calling PostAuthenticateAsync on the user service
2018-07-23 14:03:26.819 +00:00 [Information] issuing primary signin cookie
2018-07-23 14:03:26.819 +00:00 [Information] redirecting to: https://....net/identity/connect/authorize?client_id=myMobile&client_secret=myMobileSecret&response_type=code token&scope=openid profile roles&redirect_uri=https:%2F%2Flocalhost:44000%    2F&nonce=ec42d50463cc418dacbd04f1c43873d0&state=a971d692ae8f424493966023f5934b70
2018-07-23 14:03:26.866 +00:00 [Information] Start authorize request
2018-07-23 14:03:26.881 +00:00 [Information] Start authorize request protocol validation
2018-07-23 14:03:26.881 +00:00 [Information] "Authorize request validation success"
 "{
  \"ClientId\": \"myMobile\",
  \"ClientName\": \"my Mobile App\",
  \"RedirectUri\": \"https://localhost:44000/\",
  \"AllowedRedirectUris\": [
    \"https://localhost:44000/\",
    ...
  ],
  \"SubjectId\": \"2957b247-43ed-4aea-b5b4-c0a76a613942\",
  \"ResponseType\": \"code token\",
  \"ResponseMode\": \"fragment\",
  \"Flow\": \"Hybrid\",
  \"RequestedScopes\": \"openid profile roles\",
  \"State\": \"a971d692ae8f424493966023f5934b70\",
  \"Nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
  \"SessionId\": \"3e67194d4c5ba7d1c8586948377f9fe7\",
  \"Raw\": {
    \"client_id\": \"myMobile\",
    \"client_secret\": \"myMobileSecret\",
    \"response_type\": \"code token\",
    \"scope\": \"openid profile roles\",
    \"redirect_uri\": \"https://localhost:44000/\",
    \"nonce\": \"ec42d50463cc418dacbd04f1c43873d0\",
    \"state\": \"a971d692ae8f424493966023f5934b70\"
  }
}"
2018-07-23 14:03:26.881 +00:00 [Information] Creating Hybrid Flow response.
2018-07-23 14:03:26.881 +00:00 [Information] Creating Implicit Flow response.
2018-07-23 14:03:26.881 +00:00 [Debug] Creating access token
2018-07-23 14:03:26.881 +00:00 [Debug] Creating JWT access token
2018-07-23 14:03:26.912 +00:00 [Debug] Adding client "myMobile" to client list cookie for subject "2957b247-43ed-4aea-b5b4-c0a76a613942"
2018-07-23 14:03:26.912 +00:00 [Information] End authorize request
2018-07-23 14:03:26.912 +00:00 [Information] Redirecting to: https://localhost:44000/
2018-07-23 14:03:28.950 +00:00 [Information] Start token request
2018-07-23 14:03:28.950 +00:00 [Debug] Start client validation
2018-07-23 14:03:28.950 +00:00 [Debug] Start parsing Basic Authentication secret
2018-07-23 14:03:28.950 +00:00 [Debug] Parser found secret: "BasicAuthenticationSecretParser"
2018-07-23 14:03:28.950 +00:00 [Information] Secret id found: "myMobile"
2018-07-23 14:03:28.950 +00:00 [Debug] Secret validator success: "HashedSharedSecretValidator"
2018-07-23 14:03:28.950 +00:00 [Information] Client validation success
2018-07-23 14:03:28.950 +00:00 [Information] Start token request validation
2018-07-23 14:03:28.950 +00:00 [Information] Start validation of authorization code token request
2018-07-23 14:03:28.950 +00:00 [Information] Validation of authorization code token request success
2018-07-23 14:03:28.950 +00:00 [Information] Token request validation success
 {
  "ClientId": "myMobile",
  "ClientName": "my Mobile App",
  "GrantType": "authorization_code",
  "AuthorizationCode": "dc7be1793efe246ca817d7d35298b355",
  "Raw": {
    "grant_type": "authorization_code",
    "code": "dc7be1793efe246ca817d7d35298b355",
    "redirect_uri": "https://localhost:44000/",
    "code_verifier": ""
  }
}

有人可以帮助我获得一个xamarin移动应用程序以与身份服务器3一起调用api吗?

1 个答案:

答案 0 :(得分:0)

您的API需要通过Identity Server作为资源范围注册为客户端。

然后,您需要使用UseBearerTokenAuthentication在API的中间件中连接承载认证。这是必需的,以便API可以授权将Authorization头与承载模式一起使用的传入请求。

最后,您的移动应用在发出身份验证请求时需要请求该范围。但是,您还需要确保您的移动应用程序客户端已在Identity Server中注册了该范围。