No response from AcquireTokenAsync with "user_impersonation" token - asp.net-web-api

I've got a site based Web App which authenticates users via AAD login. A successful login will redirect the user back to the app with the access token (this part is all done using adal_angular.js/adal.js)
The token is then passed to a site based api which gets a new token on behalf of the user to call a downstream api as per this example (https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof) So far so good.
The downstream api, repeats this process to get another token to call another api further downstream. Here is where the problem is.
When calling AcquireTokenAsync() here, I get no response from the call whatsoever.
*Edit: No response means that I get no response from Azure AAD, using Fiddler to trace the HTTP traffic, I'm not seeing any URLs being hit as part of the AcquireTokenAsync call *
I noticed that the token I'm using at this point is now a "user_impersonation" token, where as the token received by the site based api is not. Is this significant?
Should this architecture be supported?

Ok, the problem here was my own use of async methods in my webapi. If you are calling async methods in your webapi, you need to mark your own web api methods as async. If ASP.Net doesn't know that you want to call async methods in your controller, it can cause deadlocks. (A good explanation here: http://blog.stephencleary.com/2012/07/dont-block-o...
You should never use .Result on your async methods in a web api.

Related

How to silently renew Id Token using AddMicrosoftIdentityWebAppAuthentication to Call Downstream API

I am trying to implement the BFF-Gateway pattern (no tokens in the browser) to be used with a React SPA. The BFF is using AddMicrosoftIdentityWebAppAuthentication to handle login and issue a cookie to the SPA. And it is using YARP to proxy api requests to a downstream api. I'm using Azure B2C. Everything works perfectly until the BFF id_token expires in 1 hour. At that point, fetching the downstream api access token via GetAccessTokenForUserAsync (which is called in a piece of middleware) fails:
var scope = _configuration["CallApi:ScopeForAccessToken"];
var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { scope });
ctx.Request.Headers.Add("Authorization", "Bearer " + accessToken);
Exception:
IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
ResponseBody: {"error":"invalid_grant","error_description":"AADB2C90085: The service has encountered an internal error. Please reauthenticate and try again.\r\nCorrelation ID: 622d6bd6-d06e-4142-86f2-b30a7a17b3b5\r\nTimestamp: 2022-11-25 09:31:23Z\r\n"}
This is effectively the same as Call Downstream API Without The Helper Class example and this sample, except that I'm acquiring the access token in middleware, not a controller, so the downstream YARP requests contain the access token. BTW I get the same error if I do this inside a controller per this example. And I see no soluton to this in the sample.
There is a similar question here which references the sample referenced above, but for the B2C sample I see no solution to this problem.
I also found this sample and this explanation. But this uses Microsoft.Owin to configure auth, not AddMicrosoftIdentityWebAppAuthentication. This looks promising, but is a departure from most examples I see that use Microsoft.Identity.Web.
Can you please point to the correct soluton? I need call to be able to call _tokenAcquisition.GetAccessTokenForUserAsync after the id token expires without asking the user to reauthenticate and/or the SPA to having to reload.
At the moment I am handling this issue in the SPA by catching the exception from MSAL and redirecting back to the login endpoint in the BFF which initiates the challenge. This gets me a new id_token and cookie, but this is just a temp workaround as it's very disruptive to user to be redirected away from the SPA.

How to provide login authentication for Web API in Xamarin App?

I am working on Xamarin Forms application and new to providing login authentication of the application. I have completed the design part of the application with using Entries for user id and password and button for Submit. Also, i am having web API and for authentication. Now how to connect that Web API in xamarin forms application for login.
Please guide or provide some use full samples...
Thanks in advance...!
I assume you've built out your authentication API already, and that you can make Fiddler or Postman calls directly to your controller, pass in a set of credentials, and return back a JWT / bearer token that you can then use for authenticated calls?
At this point, it's relatively simple then as you'll want to use build a proxy layer / API layer to make calls out to your API. These calls will simply mirror the ones you've made in Fiddler/Postman/your proxy of choice.
I used Refit to achieve this:
https://github.com/reactiveui/refit
Specifically, you can see on the "Setting request headers" section how they easily encapsulate it for you to pass your token.
Of course, your initial call should be to login, and then once logged in, take the JWT response back from your controller, set the token in your Keychain, and then pull it out of Keychain to set in the header.
Let me know specific questions you have? For example, which of the following do you need more info on?
Sending and parsing a response (serializing the response) from your Login action to set/assign a token in keychain?
Saving the token, and setting it in a header for subsequent calls?
Building a proxy layer using a framework like Refit to make generic outbound calls?

sharing the principal object received from an oauth2 provider between spring and angular

I have stumbled upon a problem with Spring Security and Angular.
On my BE (Spring Boot application), there are defined OAuth2 providers, such as Google, GitHub and Facebook.
My BE works fine with this providers, since I can authenticate on the desired providers.
The problem is when I try to send the principal object to the FE (Angular 6 application).
I get undefined value when i try to subscribe the value from the rest endpoint.
I assume this is due to the Spring Servlet creating a new thread for the login request.
I am doing my login request from the Angular app.
I did watch dozens of tutorials and rad so many articles, but I just can't find the answer. If it's possible for you to share some code on how it is done, or give me a link, since for sure I am making a silly mistake and can't seem to find the answer here.
Thanks for understanding, have a good day.
:)
I am assuming that you are using the Authorization Code flow from your BE to authenticate the user that interacts with your FE Angular application (you in your example). Otherwise, you would be trying to authenticate the BE Client with the Client flow and you wouldn't need to return the "principal object" to the FE application. If my assumptions are correct... read on.
The Authorization Code flow goes as follows:
1) The user somehow selects an Authentication provider (ex: Google) and that selection is returned to some endpoint in the BE as a non-authenticated request..
2) The BE Client receives this request, preferably intercepted by a filter and, since the request is not authenticatedd, redirects the browser to the selected auth provider's authorization endpoint.
3) The user then proceed to authenticate against that provider which, upon succesfull authentication, returns a response that redirects the browser to a BE Client endpoint. That redirect holds a parameter that provides a code that the BE Client will use to get an idToken representing the user. At this point, it is important to note that the browser has not been returned any response for this redirect.
4) The BE Client then proceeds to send a regular HTTP request to the provider's token endpoint along with the received authorization code. The provider then returns the idToken an HTTP response directly to the BE Client. All this is happening while the browser is still waiting for the response to the last redirect.
5) The BE Client then process the idToken (verification, validation, user details, session etc) and only then, will finally send the response to the browser patiently waiting since the code redirect. That response may provide a header or a cookie with a sessionId or token (your choice) that the FE application will be able to read or use for the given purpose.
This flow is relatively easy to implement and requires minimal SS configuration. You must keep the BE Client auth endpoint with permitAll() otherwise, you would not be able to trigger this flow. Also, make sure that, once the FE app. has received the header/cookie, all subsequent calls shall be processed as "authenticated calls". Finally, make sure to document yourself on the perils of stateless sessions as well as cookie security and always use HTTPS.
Jake.

How to get API to recognize where requests are coming from

We are developing an MVC application which links to a Web API. Currently, in order to do any calls to the API, the Javascript makes an AJAX call to the API sending a username and password for authentication. The API validates the username and password and sends back a security token. Then a second AJAX call is made to do the actual business logic, sending the security token with it.
We want to move away from this method since exposing the username and password in the Javascript is a security hole.
What we're looking at is a way to get the API to recognize where the call is coming from. For example, if the call is coming from our website, it's legitimate. Otherwise, the call is denied access.
Is there a way to do this? If so, are there any online walkthroughs on how to setup the API to do this? Thanks.

AJAX calls within MVC and Identity Server

I have been playing with Thinktecture IdentityServer3 and am keen to use it as the product looks great. However, I don't fully understand how to accomplish my flow which is probably fairly common:
Create Identity Server using Implicit flow
Setup an MVC web site
Setup a separate Web API
So far so good, as demonstrated in the examples on the site. I now wish to call the API using AJAX calls directly but for this i need an access token. It seems like a large overhead to have to route these through the MVC site itself (again, in the examples).
How can I accomplish this flow? Would it essentially blend the MVC and Javascript Client samples or is there a smoother way so the user only has to sign in once? Perhaps send the access token in a hidden field but then how would it renew?
Any help on understanding this would be great.
I've managed to come up with a solution which seems to work, not sure if it's best practice though...
Expose a method on the MVC site at AJAX/AccessToken
Method should be locked down with Authorize attribute to ensure the MVC part of the site is authenticating properly with IdentityServer
Method returns the users Access Token which was generated through the above call via MVC controllers
In JavaScript, simply use this endpoint to get an Access Token and then call the API manually
The call to get the Access Token should be secure as its within the same domain/authentication model as the MVC site itself
I've put up a sample here for anyone interested:
OIDC-Website
Check out the form post client to see the endpoints being called explicitly. You will need to hit the token endpoint to get your access token.
You should be able to use these endpoints in your AJAX calls, store the received claims and tokens in a cookie and take it from there.
Note that to renew the access token, you will also need to store the refresh token. The Implicit flow does not allow for refresh tokens (you'll need to use the Authorization Code Flow or the Hybrid Flow).

Resources