简体   繁体   中英

How to get access token from HttpContext in .Net core 2.0

I'm trying to upgrade a project from.Net core 1.1 to.Net core 2.0 there's a lot of breaking changes.

One of the things I'm currently having an issue with is that HttpContext.Authentication is now obsolete.

I've been trying to figure out how to get the Access token for the current request. I need to make a call to another API which requires a bearer token.

Old Method.Net core 1.1

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
    return View();
}

Method.Net core 2.0

This is not working becouse context isnt registered.

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = await context.HttpContext.GetTokenAsync("access_token"); 
    return View();
}

Unable to resolve service for type 'Microsoft.AspNetCore.Http.HttpContext'

I tried registering it but that doesnt work either

public ConsoleController(IOptions<ServiceSettings> serviceSettings, HttpContext context) 

In startup.cs

services.TryAddSingleton<HttpContext, HttpContext>();

Update:

This returns null

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

Startup.cs ConfigureServices

I wouldn't be surprised if it was something in the startup as there were a lot of breaking changes here as well.

services.Configure<ServiceSettings>(Configuration.GetSection("ServiceSettings"));
//services.TryAddSingleton<HttpContext, HttpContext>();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddMvc();
services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect(options =>
        {
            options.Authority = "http://localhost:5000";
            options.ClientId = "testclient";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token";
            options.RequireHttpsMetadata = false;
            options.GetClaimsFromUserInfoEndpoint = true;
        });

Startup.cs Configure

loggerFactory.AddDebug();
if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseBrowserLink();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

.Net core 2.1访问 JWT 不记名令牌

var accessToken = Request.Headers[HeaderNames.Authorization];

if you want the pure token this can help you in .net core 3.1

var _bearer_token = Request.Headers[HeaderNames.Authorization].ToString().Replace("Bearer ", "");

and remember you need to add this using

using Microsoft.Net.Http.Headers;

It ended up being a configuration issue. There needs to be a link between AddAuthentication and AddOpenIdConnect in order for it to read the cookie into the headers.

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";

                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ClientId = "testclient";
                options.ClientSecret = "secret";
                options.ResponseType = "code id_token";
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;

                options.Scope.Add("testapi");
                options.Scope.Add("offline_access");
            });

Controller

    [Authorize]
    public async Task<IActionResult> Index()
    {
        var accessToken = await HttpContext.GetTokenAsync("access_token");
        return View();
    }

Access token is now populated.

Note: I ended up digging it out of this project Startup.cs

In Controller, the token can be retrieved by reading Request.Headers dictionary:

 var accessToken = Request.Headers["Authorization"];

At other classes where HttpContext is not available, there token can be retrieved using HttpContextAccessor after injecting into services collection ( A little change from Azharuddin answer)

Register the service instance in Startup method like

public void ConfigureServices(IServiceCollection services)
{

 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
 ...
}

And inject the dependency in your controller like

private IHttpContextAccessor _httpContextAccessor;
public ClientController(IHttpContextAccessor httpContextAccessor)
{
     _httpContextAccessor = httpContextAccessor;
}

And retrieve the access token in your action like

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];

    ..........//Some other code
    return View();
}

Startup.cs:

 public void ConfigureServices(IServiceCollection services)
 {
    ...
     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    ...
 }

Controller Constructor:

private IHttpContextAccessor _httpContextAccessor;
public ClientController(IHttpContextAccessor httpContextAccessor)
{
     _httpContextAccessor = httpContextAccessor;
}

[Authorize]
public async Task<IActionResult> ClientUpdate(ClientModel client)
{
    var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
    return View();
}

This should work

您需要指定外部架构来检索令牌。

var accessToken = await HttpContext.GetTokenAsync(IdentityConstants.ExternalScheme, "access_token");

Real thanks, this is perfect !

I had this work, but with our azure tenant dedicated authority. Simply replace ****** with your tenant name.

options.Authority = "https://login.microsoftonline.com/******.onmicrosoft.com";

You also can use tenant id. Simply insert your tenant id after https://login.microsoftonline.com/

options.Authority = "https://login.microsoftonline.com/be0be093-****-****-****-5626e83beefc";
string accessToken = Request.Headers[HeaderNames.Authorization].ToString().Replace($"{JwtBearerDefaults.AuthenticationScheme} ", String.Empty);

它应该是HttpContext.GetTokenAsync("access_token").Result.ToString();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM