17

I've got a IDP implemented in IdentityServer 4. My web app client(implemented in Mvc 5) authenticates with the IDP but now I need to get the access token from the request. A way to do that in .Net Core is to use the Microsoft.AspNetCore.Authentication.AuthenticationTokenExtensions like so:

HttpContext.Authentication.GetTokenAsync("acccess_token")

I would like to be able to do the same in my .net Mvc5 web app client but I can't find any nuget package or namespace that has a similar implementation. It is important to be able to do this in MVC5 and not .net Core. Anyone came across this before?

PS- Also worth to mention that I'm using OpenIdConnect

Txugo
  • 5,008
  • 5
  • 33
  • 40

3 Answers3

22

The recently released 4.1.0 version of Katana now supports the SaveTokens property (backported from ASP.NET Core).

In order to get the access token:

  1. Update the Microsoft.Owin.Security.OpenIdConnect package to 4.1.0 (or newer)
  2. Configure SaveTokens in your Startup class:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    // Other options removed for readability
    SaveTokens = true,

    // Required for the authorization code flow to exchange for tokens automatically
    RedeemCode = true
});
  1. Read the access token in your Controller:
var result = await Request.GetOwinContext().Authentication.AuthenticateAsync("Cookies");
string token = result.Properties.Dictionary["access_token"];
Kapé
  • 4,411
  • 3
  • 37
  • 54
  • 3
    Any suggestion as to why Request.GetOwinContext().Authentication.AuthenticateAsync might return null? Even with SaveTokens and RedeemCode set to true – Hos Jan 09 '20 at 14:52
  • @kape - will this work on .Net framework 4.7.1?. I've followed and set and above properties, still the middleware does not redeem code automatically. please see my question here: https://stackoverflow.com/questions/59965137/automatic-code-authorization-code-redemption-using-latest-version-of-katana-d – nari447 Jan 30 '20 at 08:52
  • 1
    +1 What a horrible convoluted way of accessing the access_token. A half dozen SO links, and more microsoft documentation than I can handle in one day and this is the solution I find to read the unencrypted access_token? Thank you! I need this to pass to the Graph API. This also works for HttpContext. `HttpContext.Current.GetOwinContext().Authentication.AuthenticateAsync("Cookies")` – Luminous Jan 10 '22 at 21:16
  • Posting a link to the .NET CORE solution. https://stackoverflow.com/a/50623141/2567273 – Luminous Jan 11 '22 at 14:06
  • @Hos I found the solution. I think you as I make a typo in SignInAsAuthenticationType or AuthenticationType, because of it using "Cookies" didn't work. – Константин Золин Feb 11 '22 at 16:57
  • first of all +1 for the solution.. this is not there in any MS documentation but worked like charm.... Now I am able to get access_token, id_token and refresh_token from 'GetOwinContext().Authentication.AuthenticateAsync("Cookies")' but problem is how to get access_token issued and expiry time from same properties ? ExpireUtC gives Id token time... but is there any code which specificlly gices access_token expiry time? – Mahajan344 Feb 19 '23 at 12:29
0

Inside OpenIdConnectAuthenticationNotifications events the AutenticationTicket and its claims ready (there is no need to call userinfo endpoint). In order to make that Ticket available (claimsprincipal) to the httpcontext.current.user do the following inside the SecurityTokenValidated event (ReplaceIdentity is just a custom extension method to replace the claims if exists an identity with same type):

Notifications = new OpenIdConnectAuthenticationNotifications
{
    SecurityTokenValidated = (notification) =>
    {
        notification.AuthenticationTicket.Identity.AddClaim(new Claim("id_token", notification.ProtocolMessage.IdToken));
        notification.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", notification.ProtocolMessage.AccessToken));
        
        notification.OwinContext.Authentication.User.ReplaceIdentity(notification.AuthenticationTicket.Identity);

        return Task.CompletedTask;
    }

Achieve this result takes me three days of testing... but works excelent, you will have the User Identity available in HttpContext.Current.User with the other identities.

TeChaiMail
  • 21
  • 1
  • 3
-1

I spent some type before I understood, we need to send a string as an argument of AuthenticateAsync which is used in AuthenticationType and SignInAsAuthenticationType. I hilly recond to use CookieAuthenticationDefaults.AuthenticationType because it will save you from typos.