Authentication and Authorization with ASP.NET Core

2019-07-29 08:14发布

问题:

I have a ASP.Net Core MVC Web App that users needs to logon to get the id_token from the IdentityServer4 and then that id_token will be passed to webapi implemented in ServiceStack to obtain the authorization code. The subsequent call to the webapi will use the authorization code.

So far what I have read is for the Web App, it should use openid cookie token (UseOpenIdConnectAuthentication). For the webapi, it should use the bearer token. My question is how I can pass that http only cookie token from the client side browser as a bearer token in the http header. As the cookie is http only, it can't be accessed by the Javascript. Moreover, the ASP.NET Core cookie middleware encrypts the cookie, can that encrypted cookie be decrypted by the ServiceStack webapi (if the cookie is passed to the webapi)?

Am I going in the right direction? Any suggestion is welcome.

Thanks

回答1:

You can find an example of your scenario here: https://identityserver4.readthedocs.io/en/release/quickstarts/5_hybrid_and_api_access.html

The authorization code is only used to get access tokens from the identity server, it is not used to authenticate to APIs.

Here is how the flow should work:

  1. User logs in at Identity Server
  2. Your MVC app gets an authorization code and id token
    • The id token tells your MVC app who the user is
  3. The authorization code is exchanged for an access token and refresh token with identity server for the API
  4. Now the MVC app can make HTTP calls from its backend using the access token
  5. Authentication cookie is created and returned to user
  6. Front-end submits the authentication cookie with every request to MVC backend, which authenticates every request automatically that hits MVC, then when you want to call the API from there, get it as shown in the docs, and attach it to your requests


回答2:

I think the point you are missing here is that once the user is logged in, you will get the access token in the response as well when you land back on the client application. If you are using Hybrid Flow, on the client app we configure it as

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    AuthenticationScheme = "oidc",
    SignInScheme = "Cookies",

    Authority = "http://localhost:5000",
    RequireHttpsMetadata = false,

    ClientId = "mvc",
    ClientSecret = "secret",

    ResponseType = "code id_token",
    Scope = { "api1", "offline_access" },

    GetClaimsFromUserInfoEndpoint = true,
    SaveTokens = true
}); 

See the ResponseType we ask for code i.e the access code. So you need not to call or login again. Once you want to call your api just get the token like

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

// call api
var client = new HttpClient();
client.SetBearerToken(access_token);

var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
    Console.WriteLine(response.StatusCode);
}
else
{
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(JArray.Parse(content));
}

And if you using Implicit flow, your front end can get the access token using oidc-client library and user.access_token will have it.