Microsoft Azure AD oAuth flow with Headless CMS enterprise project - azure

Introduction
Recently I got hired to build out a new project that requires microsoft login to enable users from Azure AD / Microsoft 365 to be able to login in to a website that has the backbone of Strapi / a Headless CMS. See the below reference screenshot for the architecture that I have in mind.
I followed a few tutorials to integrate the oAuth flow “microsoft” explained in this tutorial and while this works fine, I need a more complete solution. (this is related to Strapi but could be any oAuth integration for a headless CMS)
The Strapi Microsoft provider only creates a user in the Strapi backend but completely ignores the returned data such as access_tokens and refresh_tokens that are mandatory to be used to parse the microsoft api’s. While this is fine if you are planning to continue with the user jwt that is generated / provided by Strapi, this but isn’t the case in my project.
Requirements System
A user should be able to login to Strapi backend with his microsoft account from a front-end website
The logged in user in the front-end should be able to get information from the microsoft graph api to get metadata of the user such as profile photo, tenant_id / group_ids, phone numbers and so forth.
The logged in user in the front-end should be able to query Strapi collection types as usual
The access_token returned by Strapi does not contain a refresh token out of the box because it uses the oauth grant flow on machine level which does not return the refresh token according to the docs.
Storing the access_token in localstorage is due to security risks not an option.
The access_token should periodically be refresh because access tokens are invalidated every 60 minutes by Azure AD.
Research done
After a little search on the web I found a library officially supported by Microsoft called MSAL
MSAL provides the tools to be able to login to microsoft AD in a react app with wrapper functions that redirect to microsoft online to login and save access_tokens etc in a secure session storage.
Unfortunately when logging on the front react app we don’t have a token to validate requests to Strapi, because we simply didn’t login to Strapi /api/connect/microsoft if we would use the MSAL library. So this is also not an option I guess.
Desired solution
We would like to be able to login to Strapi / Headless CMS via a button in the front-end and upon a success login a strapi user should be created that can execute requests on behalve of the JWT token given by Strapi, but also has the opportunity to execute requests to the external microsoft Graph API to gather meta data such as profile photo etc which are not stored in Strapi by default.
Storing the access_token in the database might be a solution but also security wise this may not be the best solution.
Lastly, the whole thing should be super secure and should automatically refresh the access token every 60 minutes. (Since the token life span of the token provided by Azure AD is 3500 seconds)
Help, tips and feedback is highly appreciated. Thanks in advance!
Cheers,
Kiwi Coder

Related

How you organize the interaction between Angular app and Xero OAuth2.0?

I am building Angular app that should interact with Xero API. Xero doesn't provide any SDK for Typescript (https://developer.xero.com/documentation/libraries/overview), but Node JS SDK seems to be the most useful lib for my task. But I am in stuck in how to organize the workflow between my app and their https://github.com/XeroAPI/xero-node-oauth2-app . I mean - I'd like to have some advises from the person who has already made similar apps (Angular + Xero) on following questions:
1) in this guide https://developer.xero.com/documentation/oauth2/auth-flow they say that user should open the page with URL like https://login.xero.com/identity/connect/authorize?... - but is there any way to make user log in without UI? If not -
2) how this process can be made in my case? In my Angular app I can make a button 'Log in to Xero' that will open new window:
window.open(xeroUrl, 'xeroAuth', 'location=yes,height=770,width=620,scrollbars=yes,status=yes');
where User log in, provide access to his organisation. The session tokens are created on the backend. But what next? How can I pass those tokens to my Angular app from that new window and then use them to make calls to Xero API?
3) Is the way to open new window for loggin in to Xero suitable for this case or maybe there is a better way to log in to Xero and get session tokens?
Thanks in advance for help.
Unfortunately, SPAs are not compatible with the Xero API.
You'll need a web server to manage your local session (OAuth flow, storage of Xero API tokens), and for your interactions with the Xero API.
While SPAs are a tempting option (they are convenient from a deployment point of view), there are changes coming to how browsers handle cross-site cookies, which break how SPAs perform session management.
I'd suggest reading https://leastprivilege.com/2020/03/31/spas-are-dead/ for more information and a discussion of the implications. The authors of the article created OIDC Client JS which is a great library for doing PKCE-based SPA auth in the browser, though it's only useful for same-domain applications now thanks to the impending browser cookie changes.
Further to this, the Xero API does not support CORS, so even once you complete the OAuth flow, the browser would be prevented from performing API requests from your Angular SPA.
To answer the specific questions:
1) The user will need to log in to Xero and grant consent for your app the first time they use your application. If you're storing server-side refresh tokens after the initial consent, your user will only need to log in to your local session, either via Xero SSO or another mechanism (user/password).
2) To create the initial Authorisation Request, it's best to use the node.js starter app. It will manage the OAuth redirect flow for you (it uses the excellent openid-client open source package for this).

node-quickbooks Express Sessions oAuth

I'm testing the Intuit OAuth2.0-demo for nodejs. link
The demo uses the node-quickbooks package within an Express server. The demo works fine but I have a question more about the general flow "best-practice" for a multi user setup.
For example:
You have your own web application that supports many users. The users login to your web application and decide to grant your web application access to Quickbooks.
How would i properly handle multiple users?
Currently, when I authorize the oAuth connection between the web app "demo" and Quickbooks the auth token is stored server-side.
The Express session is not unique to the specific logged in user on the demo web app. When I connect from different devices to my local demo web app they are all using the previously server-side stored auth token.
What is best practice for multiple users?
The demo provided from Intuit was extremely helpful but it did not provide any additional code in the boilerplate for maintaining multiple users and properly storing the access_token / refresh_token / realmId inside a storage (such as Mongo). I ended up merging this demo project with a boilerplate Passport local strategy that uses mongo. I updated the mongoose model to store the Quickbooks Online tokens. This way when the user logs into my webapp via Passport we can just pull the tokens that are associated to there user account inside mongo.
I will probably make a repo for this since I think it can be helpful to others. For now, if anyone ends up finding this thread and has any questions feel free to send a message.
Regards

nodejs find user in azure active directory

i've a nodejs API.I need to develop a fucntionnality that based on a key search a user in azure active directory.
Someone can help me or indicate me some tutos about that.
Thanks
Preface
It'll depend a bit on if you want this to be entirely service-side without user interaction or if you want to run this in the context of the user.
This answer assumes the latter. The primary benefit of this approach is it will run the search based off the user permissions required (which may be less than enabling your app to do this as a service e.g. may not require admin consent). In general, all docs can be found at Azure AD Developer Docs.
Steps / Apps you need to build
You'll want to do the following things:
Sign in the end user to your client app (e.g. here's a SPA sample).
Have this client app request tokens to your Node Web API (e.g. here's a Node Web API that accepts tokens.
Then you'll want to check out the On-behalf-of protocol. This will allow you to exchange this token for a token for the Microsoft Graph API.
You can then use the token for Graph to call the necessary Users endpoint API endpoint for users.

Why is MSDN telling me to create a OAuth2.0 client when I just want a barebone test for my API?

I have a REST API, written with express directly. Nowhere in it do I use session, and authentification is for now done using JWT.
However, I dislike having to handle, save and secure user's credentials, that is when I heard about Azure Active Directory.
Adding passport to my app was easy enought, but that's when trouble started.
First, I had to search what strategy I needed, and all of them seems to require the server to maintain sessions/remember who is logged in, all the while using JWT internally. That seems contradictory, JWT is supposed to remove the need of maintaining session.
Finally, I found this MS example which use the Bearer strategy without session.
After setting it up (changing the config file for the right tenant, client ID, changing the routes for a test app more representative of my API), I tried to use them. The protection work well since I am indeed "Unauthorized". But how do I get a valid token to send?
The MSDN guide that use that quickstart don't mention it at all, just redirecting to the AAD library for Android or iOS, implicitely telling me to develop a test app in another language when I just want a crude tool to test if my test server work at all!
That is especially frustrating since I am pretty sure it is "just" a series of HTTP(S) request on the tenant, and the call to the api with the token attached, but I can't find anything to do just that.
/!\: I know asking for something as vague as "How can I do that" isn't a good question, and this question isn't one. What I am asking is why I couldn't find some tools like POSTMan that implement OAuth and allow to quickly test and debug a OAuth protected API. What are the reason that push MSDN to tell me to write a custom tool myself instead of providing a barebone one?
The code sample you mentioned in the post is using the Azure AD V2.0 endpoint. We can use OAuth 2.0 code grant and client credentials flows to acquire the token from this endpoint.
To compose the OAuth 2.0 request directly you can refer the links below:
v2.0 Protocols - OAuth 2.0 Authorization Code Flow
Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow
In addition, the access tokens issued by the v2.0 endpoint can be consumed only by Microsoft Services. Your apps shouldn't need to perform any validation or inspection of access tokens for any of the currently supported scenarios. You can treat access tokens as completely opaque. They are just strings that your app can pass to Microsoft in HTTP requests(refer here).
If you want to protect the custom web API with Azure AD, you can use the Azure AD v1.0 endpoint.
For getting a valid token to send to your API, you'll need to do an auth request to login.microsoftonline.com and get an access token (in the JWT format). Then you can send this token to your api in the http body: "Bearer ey...".
If you want a full sample with a client app that hits that API sample you tried:
Dashboard w/ all the samples for Azure AD Converged Apps
Simple Windows Desktop App
Angular SPA
Node Web API

Azure Mobile App, Cordova client, Azure AD - refresh tokens?

This stack is shaping up to be perfect for our use case:
Azure Mobile App
Azure AD
C# backend (using GetAppServiceIdentityAsync<AzureActiveDirectoryCredentials>() to authorize users to API endpoints based on security group membership)
Cordova client
The missing piece of the puzzle for me is the ability to silently obtain a refresh token. Can the Token Store take care of this for me? Or is there a supported method of doing this either with the Cordova plugin, or in the C# backend?
I mean, the inappbrowser caches credentials, so it's not like the users have to type a password again, but still, the window pops up and it would look a bit more polished if it was silent.
Thank you.
This is currently a little more tricky for Azure AD compared to the other providers. As a starter, I recommend you check out this blog post: http://cgillum.tech/2016/03/25/app-service-auth-aad-graph-api/
It describes how to set up your mobile app backend to allow it to access the graph API on behalf of the user. Specifically, the following steps are required:
Set clientSecret (a string property) to the key value that was
generated in the Azure AD portal.
Set additionalLoginParams to the
following: (This is a JSON array value)
["response_type=code id_token", "resource=https://graph.windows.net"]
I assume this might be useful for your app anyways since you're checking security group memberships? If you'd rather not do that, then you can remove the "resource=https://graph.windows.net" parameter.
In any case, as a side effect of following these instructions, you will start receiving refresh tokens for each logged-in user, which you can use to support silent token refresh in your Cordova client.

Resources