yogihosting
yogihosting

Reputation: 6292

Unable to call Web API Secured with IdentityServer with valid Access token

The code which I am applying to call a Web API Secured with IdentityServer is given below.

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

var data = new List<WeatherForecast>();
using (var client = new HttpClient())
{
    client.SetBearerToken(accessToken);
    var result = await client.GetAsync("https://localhost:6001/WeatherForecast");
    if (result.IsSuccessStatusCode)
    {
        var model = await result.Content.ReadAsStringAsync();
        data = JsonConvert.DeserializeObject<List<WeatherForecast>>(model);
    }
    else
    {
        throw new Exception("Failed to get Data from API");
    }
}

This code fails with User is not authenticated in logs. This code is actually executing after the user is authenticated with IdentityServer. So the code line:

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

Is providing me the accessToken. But the Web API is not called, why?? I tested calling the web api with the same access token on Postman, and it was able to call the web api.

So I think there is some problem with my OpenID Connect settings. The OpenID connect settings which I am using is:

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddJwtBearer(options =>
{
    options.Authority = "https://localhost:5001";
    options.Audience = "Bond";
})
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://localhost:5001";
    options.ClientId = "xena";
    options.ResponseType = "code";
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("fullaccess");
    options.SaveTokens = true;
}); 

I tried many settings in OpenID Connect but nothing seems to work. I am showing you the working and the problem.

Here you can see the authentication part:

enter image description here

Here you can see the problem.

After authentication I visit the URL where the call to the Web API is made. I get the token with this line:

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

But when I make the api call with the token I get Showing login: User is not authenticated in the console logs. See image below:

enter image description here

The question is user is already authenticated, else I could not get the access token.

I went a little deep into this problem and put a breakpoint on the api calling code. I found that the call to the api is redirected to this url:

Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dzorro%26redirect_uri%3Dhttps%253A%252F%252Flocalhost%253A6001%252Fsignin-oidc%26response_type%3Dcode%26scope%3Dopenid%2520profile%2520fullaccess%26code_challenge%3Dwd31qWo2SpjTuncroM6qkWSvhFg-rKDVcicPOrp3-6E%26code_challenge_method%3DS256%26response_mode%3Dform_post%26nonce%3D637629779176334831.MTUwZjRlODgtZmJhYi00Y2I3LWFlYmQtNGYzNWViZmM1NWNjOWI1NDg4YTItMGI5Yy00MTk3LTk0OTQtMDIxMWI5YTg1NGIw%26state%3DCfDJ8Cuukidn-CJOlLfkzyfYd36FVs9F-zMJ_0v67GE7qgtpnN8Zd10Gnkwbhm2VgMnLCt3pihVGA3jhXFF2rYrBaj8z-j1muaq8BgUcM4Ay3yjR1i2D4gm3JrXtAUGQAulW8CqC3XWbXvS8b3U8srEXVFP2qGW91jejBVJ9YCc1v-3gTYaRmRuf45DM3Kx1bDML7Yz7s1wKyXjvSE5aS5Bq78az3gXpqOC7GIciNJ2UELFtDSJF14GEYwtHM53Ehv3p_XvU86RCYwzH9jU9CzoCeIx6ScKbRi0hTp9nybNgj3PlOvzMZWg4taxiOK3yKxroFEK_GGAY9oK_ZzsRodVcoJp-2BGA_yceJbU0GeoPic111cjUC4_ml1r_gBiq-o7dDBWRRJsFyScGVRNDj8vyL7k%26x-client-SKU%3DID_NETSTANDARD2_0%26x-client-ver%3D6.7.1.0

So quite obvious, the app is concluding that I am not authenicated so I cannot make api call. But I am already authenicated, so how can I solve this?

Upvotes: 1

Views: 1057

Answers (3)

yogihosting
yogihosting

Reputation: 6292

I found the solution by changing the [Authorize] attribute in the Web API to:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

and then also add authorization on the Starup.cs of the Client Project (which contains the Web API).

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme);
// other authorization of oidc which is given in the question itself.

Upvotes: 0

Tore Nestenius
Tore Nestenius

Reputation: 19901

My recommendation is to put the WEB API on is own service to follow the principle of separation of concerns. When you mix IdentityServer and web applications and API's , you are asking for trouble.

Upvotes: 1

Brando Zhang
Brando Zhang

Reputation: 27962

As far as I know, the HttpContext.GetTokenAsync method will get the token based on the authentication scheme.

I suggest you could try to specific the authentication scheme and try again. Like below:

        var re = HttpContext.GetTokenAsync("oidc", "access_token");

Upvotes: 0

Related Questions