OIDC: Keep access tokens valid during long-running server operations - http

If a user authenticates via OpenID Connect on a client and triggers a long-running server-side request, how can the server keep the access token valid if the operation takes longer than the access token's expiration time?
We have an application suite consisting of several server-side backend applications (typically accessed via REST, HTTP, and/or WebDAV), several web frontend applications and several client-side (i.e. desktop) applications. We already support the Basic and Kerberos/Negotiate authentication schemes and are currently adding support for OpenID Connect.
Our backend applications are typically accessed by the web frontend and client applications, other server-side backend applications, and 3rd party customer applications when our software is integrated into their system. We currently pass OpenID access tokens via the Bearer scheme to the backend applications.
In a typical scenario, a user (authenticated on a local client or in a web frontend) triggers a server-side operation which may possibly run for several minutes, hours, days, or even weeks. This operation accesses other backends on the user's behalf, e.g. a Web-DAV based server-side file system, to access additional data. All backend applications need the user's authentication information to grant access and access further user details for authorisation (e.g. to only grant access to the user's own files).
Obviously, this means that the access token provided with the original backend call may expire before the operation is completed. The server therefore needs a way to refresh the access token without user interaction. Our code can already do this if it knows the user's refresh token (using the refresh token and the application's client ID and secret to access the OIDC Token endpoint).
But how can we "correctly" pass the refresh token to the server?
The client has (potentially) the full set of ID, access, and refresh tokens. But from what I understand, the Bearer scheme expects that the passed token is the access token. Compatibility is important here, since our backend applications may also be accessed by 3rd party client applications. Assuming that getting the refresh token into the server application is the correct approach at all, we therefore still have to support situations where the caller can only provide an access token (with the obvious implications that in these cases, long-running operations will not be able to access other backend services on the user's behalf).
I could imagine the server accepting either an access token or a refresh token via Bearer. But from what I understand, the only "argument" a client may pass with a correct Bearer authentication header is a single Base64 encoded string, i.e. the (access) token. The client could pass an access or refresh token here, but I don't see how the server could then tell which it is, as to my knowledge both token types are opaque.
I understand that the original idea is for server operations to be short lived, so that keeping the access token up to date is the client's responsibility. But surely we cannot be the first who do need to combine OIDC with long-running server-side operations. Is there an accepted way to pass a refresh token to a server, or, alternatively, a completely different approach that I'm missing?

Related

Proper OAuth2 authentication flow for a web API using the EWS Managed API

I've been reading through a bunch of documentation for using OAuth with Azure AD, but am still completely confused about how to properly implement things for my situation. Hopefully someone can steer me in the right direction.
I have created an ASP.NET Web API application that uses the EWS Managed API to access Exchange on behalf of different users. My application exposes endpoints such as /Mailbox/Messages and /Appointments with the intent that some front end web application will eventually use them to retrieve a user's emails and appointments. Currently the endpoints are working using basic http authentication, but I'd like to update them to use OAuth. The application has been registered in my Azure AD instance and I've configured it to require the "Access mailboxes as the signed-in user via Exchange Web Services" API permission.
Since the front end hasn't been implemented yet, I've been trying to test by manually calling the authentication endpoint. This prompts me to log in and provide consent. If I consent, I'm redirected to the callback URL that I provided when I registered the app with the authorization code contained in the query parameters. I'm still not quite sure how I'm supposed to be using this callback, but for the sake of testing I currently have the callback redeem the authorization code for an access token. This is done by calling the AcquireTokenByAuthorizationCode method on an instance of the AuthenticationContext class and providing my application's id and secret. Again, just for the sake of testing I return the access token to the browser. I can then call my aforementioned endpoints (after some modifications) with this access token and get the emails for the user. I'm guessing much of this is not the correct way to be doing things.
Some of my points of confusion:
What should the callback that I registered in Azure AD actually be doing when it gets the authorization code? Is this intended for a different type of application? Perhaps one that isn't just playing the role of a middle man.
I'm trying to make my application somewhat RESTful, so I don't want to have to maintain the access tokens on my end between requests. As such, does it make sense for my endpoints to expect that the access token be provided in the authentication header for each request? If so, does that mean the front end application should be responsible acquiring the access token and passing it to me?
Being completely new to OAuth and Azure, I'm not sure if any other details are pertinent, but I can provide more information as needed.
What you are implementing is this scenario: https://learn.microsoft.com/en-us/azure/active-directory/active-directory-authentication-scenarios#daemon-or-server-application-to-web-api
Here's how it works:
Your client app redirects the user to sign in at the authorization endpoint
Your client app gets back an authorization code (if using the auth code grant flow, there are others)
The client app exchanges the code for an access token for your API app
It will need to provide its client id and secret along with the code and the API's resource URI to get it
The client app calls to your API app, passing the access token in the Authorization header
Your API app then validates the access token, and requests for another access token from Azure AD for the Exchange API
It will pass the access token sent by the client app, along with its client id and secret and the Exchange API's resource URI to Azure AD
Your API app receives an access token so you can call to the Exchange API as the user
And to answer your two questions:
Authorization code flow is not used with APIs, only with apps that have a user signing in, thus the redirect URL is basically never used
Your API can and must expect and authenticate the access token for it to be in every request. But the access token it uses to call the Exchange API can and should be cached on the API's side. This is provided out-of-the-box with ADAL, though the tokens are only in memory.

Securing communication between mobile app and RESTful service WITHOUT a username and password

I've been trying to work out if it is possible to authorize communication between a mobile app and my ASP.NET web api service without the user having to authenticate with a username and password. This is important because users of my app don't login at all and never will. All traffic will of course be sent over HTTPS.
This means I can't use OAUTH or BASIC authentication to authenticate the traffic as these require credentials.
So I need some method to securely store some kind of authentication token that is packaged in the app that is only accessed when it needs to communicate to the server and can't be "discovered" by a determined hacker.
This may of course not be possible.
Thanks.
In general it is not possible. Your server should never trust it's clients. Hackers can examine your client app and create equivalent one.
But you can make life of hackers significantly harder, if you:
Use custom cliest sertificat for HTTPS, look here.
Use temporary access keys in http request. Application should request for new temporary access key your server. Part of the key server will send in response and another part will be sent via Cloud Messaging. Combine parts of the key in some non-trivial way.
Obfuscate your app.

How should I share authentication from a desktop application to a web application using OAuth 2.0

I have a RESTful API written in ASP.Net that implements OAuth 2 for authentication, and it's currently accessed through a web application. I've also got a legacy desktop client that accesses the same resources directly (not through the RESTful API and without OAuth, but using the same login credentials and hitting the same database). The requirement I'm trying to meet right now is to allow a user to click a link in the desktop application in order to open the web app to a specific screen, and when they do, to have the web app authenticate automatically so that they don't have to manually log into it (since they've already logged into the desktop app).
I'm trying to work out how I can handle this within the constraints of the framework. I'm not too familiar with OAuth 2 in general, but from what I understand I shouldn't share tokens between clients and there are no flows specifically for this kind of hand-off (unless I'm missing something). Worst case scenario, I could generate a temporary token outside of OAuth that's used by the web client to authenticate rather than a username and password, but I'm hoping to avoid stepping outside of what's already in the framework to do what I need to do.
So the question is this: is there some decent way built into the OAuth 2.0 framework to handle this sort of "handshake" between two applications, or should I just build my own method of dealing with it?
Using temporary one-time tokens is actually part of OAuth spec (authorization_code grant type). In this case this short-lived code can be exchanged for access_token (and refresh_token). You will have to implemenent generating and validating of this authorization_code.
If you are using OWIN OAuth middleware:
You can generate the code at separate API endpoint accessed by your desktop client app.
After receiving token, pass it to your browser and direct it to auth endpoint with grant_type=authorization_code over secure connection. Example: call Process.Start("https://example.com/ExternalLogin/authorization_code_goes_here"). At the webpage redirect user to your OAuth Token endpoint with grant_type=authorization_code.
AuthenticationTokenProvider.Receive will be called, in which you will validate your token. (Example code here).
After successful validation OAuthAuthorizationServerProvider.GrantAuthorizationCode will be called, in which you will process the authenticated user in the same way you process it with grant_type=password.
Remember that your token validation logic should ensure that your tokens are short-lived, usable only once and transmitted over secure connection.
This is sometimes called "single sign-on" if you want to research this topic further.

Authenticate native mobile app using a REST API

Like the Facebook application, you only enter your credentials when you open the application for the first time. After that, you're automatically signed in every time you open the app. How does one accomplish this?
There's a commom line in all auto-login implementations
Upon an initial login, a token is received and stored on the client side
Upon subsequent visits, if token is available on the client side, the server resolves the identity and logs in automatically
Now concrete implementation variations can be numerous. The token can be a session ID (encripted or not), OAuth token, custom token, username and password should be avoided. Storing token can be on within a browser cookie, browser local storage, can have a server counter-part. Security is the major concern. Generally about the topic you can read more here https://softwareengineering.stackexchange.com/questions/200511/how-to-securely-implement-auto-login
You have an interesting explanation of how does Stackoverflow do it https://meta.stackexchange.com/questions/64260/how-does-sos-new-auto-login-feature-work.

Workflow of JWT authentication

I'm tasked with creating a service-oriented ecosystem for a client. The whole thing is going to be REST based and built in ASP.NET, but my question is technology-agnostic. We want to have a centralized authentication service that issues JWT tokens and claims that are trusted by the other services in the environment.
My issue is this - what's the first thing that a web client (browser) requests? All of the diagrams I've seen (I'll try to add a couple of example links) make it seems as if the client needs to be self-aware and realize that they're going to need a token before they make the first request to the functional REST service, which seems, well, janky to me.
The way I want it to work is that they just attempt to access the secured resource, but there's no auth token with the request my REST service challenge them for user/password, but then delegate the authentication to my auth service. So:
Browser requests restricted resource on REST service
REST service returns 401
Browser gathers credentials, sends to same web service
REST service connects to the authentication service, passing along the Auth header from the client's request
Auth service creates the JWT token and returns it to the REST service
REST service validates the JWT and replaces the Auth header with the JWT token
JWT token is persisted for subsequent requests, up to expy setting
...am I completely off about this? Does the web client need to know that there's a separate auth service involved and make one request there to get their JWT, and then a second request for the REST resource passing the JWT? That seems clunky to me, I hope that's not the idea.
Also, another n00b question - is the JWT token automagically kept by the web clients and re-sent with every request so I don't have to go through the auth service step each time? Is that what the expiration setting is for?
TIA.
See figure 1 here for an example of what I mean: http://msdn.microsoft.com/en-us/library/hh446531.aspx
Starting with your last question will make the rest of the answers clearer:
"...is the JWT token automagically kept by the web clients and re-sent with every request.." - The idea is to issue JWT once, send it to the client so client can save it and send it on each subsequent request. This way your front-end app will send username and password just once and then use JWT for authentication. You will have to store the JWT using browser storage (local or session) or cookies (common fallback for older browsers).
"...Does the web client need to know that there's a separate auth service involved..." - You will need to send the username and password to a service in order to have the JWT issued. You could implement it with just one request, but you need to send credentials to the service (provided by the user), receive JWT as part of response and store it (as above). It might be easier to do it on a separate request, depending on requirements and implementation.

Resources