Can a ASP.NET Core MVC web app receive a new Azure AD access token during an Axios Request? - axios

Based on this reading the AuthorizeForScope tag in a controller will handle getting a new access token if there is an issue with the previous access token. This could be if the access token expires or the cache of the server is cleared and and the token was stored in cache similar to the implementations shown in the default Azure AD sample codes on github for calling MS Graph. This does exactly what it should if you are doing full page redirects using the browser URL by accessing a GET controller in my MVC web app. However, if you are using a SPA like VueJS we are not doing full page reloads but instead Axios requests. So if the controller has the AuthorizeForScope tag and the access token was cleared from cache then the tag does what it is suppose to it and creates a redirect for the new challenge to get the new access token. This redirect is returned to Axios as a redirect 302 error. I am able to intercept this event and convert this error to a 401 error and handle it on the front end by pushing the user to a custom login page with a button to do a new challenge manually. However, can this all be done without effecting the flow of the user experience? For example can a new token be obtained without a full page redirect and handled on the web server despite having delegated permissions for my app?
OR is this not possible and since the methods in my controllers do other stuff and not just use this token, should I just run a simple MS Graph function at the beginning of all of my methods in every controller to trip the error early to send that 401 error so they can hit the challenge button and get a new access token with a actual page redirect.

Related

Getting logged in user from .Net Core 3.1 Web API

I've been struggling with this implementation for months. I had a workaround but it's far from ideal.
I've been struggling to get access to the current logged-in user from within my Web API. Ordinarily, I'd perhaps log in through the client and then authorise through a token. The problem I have, however, is that the client isn't the software that makes the log in request.
The client is written in Unity 3D and is embedded into the site. It shares data with the site via a Web API. Before the user gets access to the client, however, they have to log into the site through a standard .Net Core login system. So, as you can see, there's no way to pass an authentication token to the client. What I'm trying to do is have the Web API respond to requests by accessing only the details of the current logged-in user.
At the moment, I've tried gaining access to user data via HttpContext but in order to do that, I've had to enable Windows Authentication in the project. But now, all calls to the Web API result in a 401 error as the client itself can't send any authentication information.
So, what I need to do is find a way to get current logged in user information inside a Web API where the API doesn't need to receive any tokens or other information to do it.
Any ideas how that might be possible?
UPDATE 5/8/2020
Passing authentication token from web to Unity 3D
Since you have less detail about client, I take a example about Unity Web Player and browser communication.
Calling Unity web player content functions from the web page
The Unity Web Player object has a function, SendMessage(), that can be called from a web page in order to call functions within Unity web player content. This function is very similar to the GameObject.SendMessage function in the Unity scripting API. When called from a web page you pass an object name, a function name and a single argument, and SendMessage() will call the given function in the given game object.
<script type="text/javascript" language="javascript">
<!--
//initializing the WebPlayer
var u = new UnityObject2();
u.initPlugin(jQuery("#unityPlayer")[0], "Example.unity3d");
function SaySomethingToUnity()
{
u.getUnity().SendMessage("MyObject", "MyFunction", "Hello from a web page!");
}
-->
</script>
You can use to send authentication token.
So, what I need to do is find a way to get current logged in user
information inside a Web API where the API doesn't need to receive any
tokens or other information to do it.
If we have a API to get tokens as you expect, then you access all APIs with this token. Authentication will be useless and system becomes unsafe. Because everyone can access with the magic api.

How to get a bearer token to access an API from an MVC application

My user flow is as follows...
User requests a protected resource.
User redirected to authentication provider (e.g. Google)
User redirect back to ASP.Net MVC application which uses cookie authentication.
This works great, and following the MVC sample application from the IdentityServer samples I can see a list of claims for my user.
So the main page of my application is rendered using an MVC view, I have other resources which are authorised via resource authorisation and this works great.
The next part of my application is an API. Let's say it's api.domain.com/stockquote
This should only be useable by authorised users of my application and not publically available.
I have successfully made an Angular JS application with Identity Server and understand that when the token is returned I am able to get the value of /id_token from the URI, store it in localstorage and then use it to form an authorisation header for the API e.g. Authorization=Bearer {token} . Again works nicely.
However, now I am authenticated into my MVC application how do I get this token and put it into local storage so that I can create a header for my API calls?
Can I extract it from the cookie somehow?
Is it a good idea to output it in the HTML stream so that JS can pick it up and put into localstorage (guessing now).
Can I use the token endpoint to somehow get this token?
One way to handle this might be to change the way you authenticate. Instead of handling the callback in MVC on the server side, handle it in JavaScript. Then the token is available for you to store in local storage. This might not be possible if you are making requests on the server side that uses the token as well.

Confused about callbacks in OAuth flows

Say you have a REST API that you want to protect with an OAuth based authentication system. The regular flow using the website I'm using is:
user clicks a link to login to google
google makes a request to the callback you specified
your application responds to the callback by taking the given tokens and requesting the user data, finding what that user data corresponds to on the database and giving you back a session cookie for the web application and an HTML redirect (for example to the home or whatever you prefer)
Basically the callback endpoint transforms google tokens into your web application session cookies.
Now I'm wondering: how would that work for a mobile application that doesn't know anything about cookies or redirects? It could do:
on google button click, make HTTP request to the google auth URL
google responds with the callback URL you specified
the app makes another request to the above mentioned callback URL to your application
your application returns a cookie session value and a redirect URL to the homepage
the mobile applications forgets about the last redirect URL and takes the cookie session value and uses that for any other requests to the API
Is that right?
One way to do it is that you create an embedded web component on the native mobile UI, you set its URL to the authorization endpoint, the user logs in and authorizes your app, the Authorization Server redirects to your callback URL with an Authorization Token.
Your app subscribes to the changes of the web component, and when it detects the callback URL it takes the Authorization Token, destroy the web component, and calls the REST API to get an Access Token, and then access any protected resources.
Related posts:
Integrate oauth2 with native (iOS/Android) mobile application
Oauth2 flow without redirect_uri
OAuth2 for front end applications
Disclaimer: I never implemented this and I don't work with mobile apps, I just got this from reading stuff.

How to avoid going to a user for access token generation

I am writing a server which connects to a facebook account on behalf of a corporation, so the account is known and fixed.
The method my prototype code uses to access the facebook feed is as follows
1) use a WebBrowser UI component top request https://www.facebook.com/dialog/oauth with client_id (AKA AppID) and redirect_uri parameters passed. When this returns it either returns an access token or, if this is not cached by the web browser, prompts the user to login. If this is successful the Web Browser response is fired with the access token.
From there I
2) check the access token is application to the app, and then
3) generate a longer life token from that.
4) read the feed
It seems to work OK.
However my problem is that when I turn this into server code, there will be no user. So when the access token is not known I have no way of getting it.
Is there a way around this??
Thanks.

Facebook authentication and Ajax

I am building a Facebook application, and using the oAuth 2.0 protocol for authentication/authorization.
When a user first visits my app I am using the protocol and store the access token in order to make future requests to the Graph API. The problem occurs when the access token expires and the user is using ajax.
When the ajax request is sent I try to retrieve information from the Graph API using the access token, but since it expired I get a JSON saying the access token is invalid. Now, I can send a response back to the client saying the access token expired and on the client side I can redirect him to https://www.facebook.com/dialog/oauth to go through the authentication process again. However, since the whole process is in Ajax, redirecting the user will hurt the usability of the application.
Is there any other way I can use the protocol to get a new access token without needing to redirect the user's browser to get a new access token? Maybe something on the server side?
You just need to ask for the offline_access permission, then your access_token will not expire.
As Rafael notes, you can ask the user for offline_access and then the token should never expire. However, in practice, the access token does expire when a user changes their password or uninstalls/reinstalls your app, so you'll need to build a way for the user to reauthenticate themselves so you can update their token. I suggest redirecting them to a login page that should (ideally) just send them right back where you tell them to go without them having to do anything, and using deep linking to put them right back in your app where they left off.
I'm encountering this issue as well. One solution I came up with is as follows:
Create an async method called isAccessTokenValid()
Invoke isAccessTokenValid() before any method that will require FB interaction
If access_token has expired. save the current uri to the session, along with any form data entries (if any), and start the re-authentication process again.
Once the user has re-authenticated, bring up the stored uri.
This is a bit dirty, but I haven't seen a cleaner solution yet.