11

I have a web Application which authenticates a user to an Identity Server 4, using an implicit client. I need the access token for this user so that I can make a call to another API.

To be clear:

  1. I have an identity Server. Created using Identity server 4.
  2. I have the web app in question created in Asp .net core mvc.
  3. API created in .net core.

The Web application authenticates the user against the identity server. Once they are authenticated we use bearer tokens to access the API.

 services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

 services.AddAuthentication(options =>
            {
                options.DefaultScheme = "cookie";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("cookie")
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = Configuration["ServiceSettings:IdentityServerEndpoint"];
                options.ClientId = "f91ece52-81cf-4b7b-a296-26356f50841f";
                options.SignInScheme = "cookie";
            });

The user is authenticating fine and i am able to access the controller below. I need an access token for this user so that i can make a request to another API.

[Authorize]
public async Task<IActionResult> Index(int clientId, string error)
{
        ViewData["Title"] = "Secrets";

        if (User.Identity.IsAuthenticated)
        {

         // All of the below attempts result in either null or empty array
         var attempt1 = Request.Headers["Authorization"];
         var attempt2 = await HttpContext.GetTokenAsync("access_token");
         var attempt3 = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];

         var attempt4 = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");

        }
        return View();
    }

The following does contain a header called cookie. Is there a way of getting the access token out of that?

  var h = _httpContextAccessor.HttpContext.Request.Headers.ToList();

How can i find an access token for the current authenticated user? Using Implicit login.

Note on Hybrid vs implicit login: I cant use hybrid login due to the issue posted here Authentication limit extensive header size As i have not been able to find a solution to that problem a suggestion was to switch to an implicit login rather than hybrid. Implicit does not appear to create the giant cooking the hybrid did.

I have been following this to create the implicit client Getting started with Identityserver 4

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • It should rather be `Authorization` than `Authentication`, this is the default convention of passing the token. In attempt1 you have the incorrect header name and in attempt3 you have a typo. – Wiktor Zychla May 28 '18 at 12:26
  • changed but no effect _httpContextAccessor.HttpContext.Request.Headers.ToList(); does not contain an authorization header. – Linda Lawton - DaImTo May 28 '18 at 12:30
  • Most likely its gone. You are authenticated against third party provider, now all info needed is stored in a cookie created by asp.net, and access token is no longer relevant. – Evk May 28 '18 at 12:46
  • Its my identity server not a third party, I need the access token to access the api sent as a bearer token. So anyway to get the access token out of the cookie? – Linda Lawton - DaImTo May 28 '18 at 12:47
  • It's yours, but in the context of this application it's still considered third party (external). I don't think access token is available anywhere in cookie or anywhere else in this scheme. – Evk May 28 '18 at 12:58
  • Is your middleware configured to put the token in HttpContext's Request object or Item object? – user1672994 May 28 '18 at 12:59
  • @user1672994 not sure i understand what you mean. can you give me some more information. – Linda Lawton - DaImTo May 28 '18 at 13:00
  • Usally, the middleware controls what should happen after authentication. And there you can put the required token if it's not being added by identityserver (Since I've never used IdentityServer - not sure how it's work). Like this https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs#L144 which saves JWT access_token . – user1672994 May 28 '18 at 13:06
  • Take a look at my answer from a few weeks ago: https://stackoverflow.com/a/50310709/666958 – Saša Ćetković May 29 '18 at 07:26

3 Answers3

17

By default the OpenID Connect middleware only requests an identity token (a response_type of id_token).

You'll need to first update your OpenIdConnectOptions with the following:

options.ResponseType = "id_token token";

You can then save the tokens to your cookie using:

options.SaveTokens = true;

And then finally, you can access the token using:

await HttpContext.GetTokenAsync("access_token");

Note that you will also need to set the AllowAccessTokensViaBrowser flag in your IdentityServer client configuration when using the implicit flow.

Scott Brady
  • 5,498
  • 24
  • 38
  • options.ResponseType = "id_token token"; <-- wont that make it a hybrid grant type instead of an implicit? Is there no way of using this with a implicit grant type? – Linda Lawton - DaImTo May 31 '18 at 11:54
  • No, that’s implicit still: https://www.scottbrady91.com/OpenID-Connect/OpenID-Connect-Flows – Scott Brady May 31 '18 at 11:56
  • (face palm) I thought adding any ResponseType would make it hybrid! I think i read something wrong somewhere..... I will give this a try tomorrow thanks – Linda Lawton - DaImTo May 31 '18 at 12:19
  • OK this is working but, HttpContext.User does not contain all the claims. Its strange becouse I can see that context.User is set in the AddOpenIdConnect events. – Linda Lawton - DaImTo Jun 14 '18 at 08:14
  • Your identity token no longer contains identity scope claims. You need to use the user info endpoint now. There is an option to do this in the OIDC middleware – Scott Brady Jun 14 '18 at 08:17
  • options.GetClaimsFromUserInfoEndpoint = true; <-- already set. Your right though i can see that the claims are no longer in the idtoken but they are in the access token. I wonder if i can figuer out how to rip them out of that. – Linda Lawton - DaImTo Jun 14 '18 at 08:55
  • It is still not working for me.. any other possible places that I would miss? – superninja Feb 21 '19 at 01:01
  • Posting a link for people looking for the solution that isn't for .NET CORE. https://stackoverflow.com/a/59085792/2567273 – Luminous Jan 10 '22 at 21:23
1

Use options.SaveTokens = true then grab your access token from the claims or use HttpContext.GetTokenAsync here's the link to the blogpost with example: https://www.jerriepelser.com/blog/accessing-tokens-aspnet-core-2/

bychkov
  • 1,503
  • 1
  • 13
  • 26
0

I solved using the IHttpContextAccessor:

 var token = _accessor.HttpContext.Request.Headers["Authorization"];
 return token.ToString().Replace("Bearer ", string.Empty);