惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Security Latest
Security Latest
C
Cisco Blogs
P
Palo Alto Networks Blog
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
C
Cyber Attacks, Cyber Crime and Cyber Security
NISL@THU
NISL@THU
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
D
Docker
Google Online Security Blog
Google Online Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Announcements
Recent Announcements
T
The Exploit Database - CXSecurity.com
G
Google Developers Blog
Schneier on Security
Schneier on Security
小众软件
小众软件
爱范儿
爱范儿
GbyAI
GbyAI
J
Java Code Geeks
T
Tailwind CSS Blog
Cisco Talos Blog
Cisco Talos Blog
The Hacker News
The Hacker News
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
B
Blog RSS Feed
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Securelist
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Y
Y Combinator Blog
S
Schneier on Security
Latest news
Latest news
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 叶小钗
F
Fortinet All Blogs
M
MIT News - Artificial intelligence
PCI Perspectives
PCI Perspectives
V
V2EX
V2EX - 技术
V2EX - 技术
O
OpenAI News
W
WeLiveSecurity

江边的旱鸭子

Unpacking the Data Structure of Manus Session Qwen2.5 vs. GPT-4o - Unlocking Coding Potential with Cline From Research to Product: Customer Insights on Prompt flow 2023大阪东京走马观花五日流水账(下) 2023大阪东京走马观花五日流水账(中) 2023大阪东京走马观花五日流水账(上) 2022年我想练的歌单 蔡剑爵士吉他课程二年级笔记 2020云南游记(下) 2020云南游记(中) 2020云南游记(上) Jazz guitar foundations 吉他保养简记 音乐基础速查笔记 开车有三宝 邂逅爵士乐——记在台湾的一段美好经历 2021 微软内推,已协助超过十余位候选人拿到 offer Hands-on linear regression for machine learning 三星Note9与米10Pro拍照对比
Getting started with AAD integration in JavaScript
Authority · 2021-04-14 · via 江边的旱鸭子

Relationship between OAuth2.0, AAD and MSAL

Definitions

OAuth 2.0

OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 focuses on client developer simplicity while providing specific authorization flows for web applications, desktop applications, mobile phones, and living room devices.

Azure Authentication Directory

One of OAuth 2.0 and OpenID Connect standard-compliant authentication service enabling developers to authenticate work or school accounts. It’s the implementation which supports OAuth 2.0. It’s the component of Microsoft Identity platform.

Microsoft Authentication Libraries

Open source libraries for several clients to authenticate users using AAD, Microsoft personal accounts (MSA), and social identity providers like Facebook, Google, LinkedIn, Microsoft accounts, etc.

Usage scenario

oauth-scenario

Workflow and implementation

Authentication flow

auth-flow

Two APIs

Only two APIs requested from client-side, very simple. Notice that /oauth2/v2.0/authorize is document type.

auth-document

Redirect URI setup

For CORS and redirect target from sign-in page usage, should configure it on both Azure Portal and codebase.

Configuration on Azure Portal

reply-uris-config

oauth.html

Usually we will set two reply URIs, one is probably the homepage as redirect target after signed in, another is used for requesting token silently. The silent token refresh loads an iframe using that empty oauth.html file, and that same oauth.html file needs to receive the response back, so the acquire token silent flow provides the /oauth.html endpoint as the redirect URI. This is different from the user-facing flow because there is no iframe that the middleware loads into the page, redirecting back to oauth.html will not hook into React or MSAL and auth would halt – it must redirect back to your react app in the user-facing flow.

Code configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const config = {
auth: {

clientId: "11111111-1111-1111-111111111111",

authority: "https://login.microsoftonline.com/common",

redirectUri: "https://localhost:3000",
postLogoutRedirectUri: "https://localhost:3000/logout"
}
}

const loginRequest = {
scopes: [`${resourceEndpoint}/.default`]
}

The authority is a URL that indicates a directory that MSAL can request tokens from, for more details check the MSAL Application configuration options.

Scopes and permissions

Applications that integrate with the Microsoft identity platform follow an authorization model that gives users and administrators control over how data can be accessed. /.default represents OpenID Connect scopes, for more details check the Permissions and consent in the Microsoft identity platform.

Sign-in with redirect

It’s no need to redirect to sign-in page every time if auth is not expired, just go ahead. You can also sign-in with a pop-up window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let username = "";

const msalInstance = new PublicClientApplication(config);

function handleResponse(response) {



const currentAccounts = msalInstance.getAllAccounts();

if (currentAccounts === null) {

msalInstance.loginRedirect(loginRequest);
} else if (currentAccounts.length > 1) {

} else if (currentAccounts.length === 1) {
username = currentAccounts[0].username;
}
}

msalInstance.handleRedirectPromise().then(handleResponse);

Authorization code

After signed in successfully, page will redirect to the redirect URI we set before with the authorization code. MSAL.js library will handle it automatically, we can observe the code on the navigation bar.

hash-code

Then the library will parse the authorization code and send the request to get token back directly, all logics encapsulated. Here is the structure of the decoded code.

auth-code-deserialized

Acquire a token with a redirect

The pattern for acquiring tokens for APIs with MSAL.js is to first attempt a silent token request by using the acquireTokenSilent method. When this method is called, the library first checks the cache in browser storage to see if a valid token exists and returns it. When no valid token is in the cache, it sends a silent token request to AAD from a hidden iframe.

The silent token requests to AAD might fail for reasons like an expired Azure AD session or a password change. In that case, we need to redirect or using a pop-up window to acquire tokens.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const accessTokenRequest: AuthenticationParameters = {
scopes: [`${resourceEndpoint}/.default`],
authority: this.authority,
redirectUri: "https://localhost:3000/oauth.html",
account: this.account
}

msalInstance.acquireTokenSilent(accessTokenRequest).then(function(accessTokenResponse) {


let accessToken = accessTokenResponse.accessToken;
}).catch(function (error) {

console.log(error);
if (error.errorMessage.indexOf("interaction_required") !== -1) {
msalInstance.acquireTokenRedirect(accessTokenRequest);
}
});

Why use redirect way?

If users have browser constraints or policies where pop-ups windows are disabled, you can use the redirect method. Use the redirect method with the Internet Explorer browser, because there are known issues with pop-up windows on Internet Explorer.

Choice of MSAL.js

You will find so many packages when you visit MSAL.js repository, APIs used above should be compatible across the packages, then question comes: how to make a choice?

Besides node package using in the server-side, I recommend msal-browser (Microsoft Authentication Library for JavaScript v2.x) or other UI framework wrappers based on it, for its implementation of OAuth 2.0 Authorization Code Flow with PCKE as well as it’s OpenID-compliant.

msal-package-structure

These packages are just official engineering implementations, not so well-documented yet, I had to read the source code for debugging before. Anyway as long as you master the workflow of authentication, it would not be too complicated.

Migration from AdalJS to MSAL.js

AdalJS is the legacy library for AAD authentication used by so many dated products. If you don’t have any idea about this section, the official document explains Why switch to MSAL clearly.

Tips

  • You may need to change the reply URL type from Web to SPA as MSAL.js required. AdalJS supports both two types, so this change will not block online client services.
  • Need to specify the accessTokenAcceptedVersion to 2 and signInAudience to AzureADandPersonalMicrosoftAccount in the manifest if you want to support both AAD account and MSA account. These settings will not break online client services as well.
  • You can just import the MSAL.js distribution script to your app then test if the current AAD configurations are satisfying both SDKs.
  • If there is an auth service for the app, you can just do silent login with ssoSlient().
  • Remember to test all kinds of audiences of the customers and all provided resouce endpoints with access token.

Quick login verification on you app page

PoC (Proof of concept) or verfication always needs quick moves. For the migration scenario, we have to make sure the AAD configurations are correct as well as compatible to make both AdalJS clients and MSAL.js clients login successfully at first stage. To do the quick login verification, the authentication client class need to be exposed to Window global no matter AdalJS or MSAL.js, then we can do experiment on the console of browser.

For MSAL.js

Please refer to the document, it’s similar to the codes demonstrated above.

For AdalJS

The docs for AdalJS are much fewer than MSAL.js probably becasue it has been deprecated. And different versions of AdalJS seems to have few subtle API as well as behavior changes, so you may need to update the code below to make it work. My test code is based on AdalJS v1.0.8.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var authContext = new AuthenticationContext({
instance: "https://login.microsoftonline.com/",
clientId: "Client ID of AAD app",
redirectUri: "Reply URL of AAD app",
postLogoutRedirectUri: window.location.href,
cacheLocation: 'localStorage',
endpoints: { graphApiResourceEndpoint: "https://graph.microsoft.com/" },
})


authContext.config.displayCall = function (url) {
authContext.config.displayCall = null;
var popup = window.open(url, 'auth-popup', 'width=800,height=500');
var intervalId = window.setInterval(function () {
try {

if (popup.location.pathname.indexOf('/signin') >= 0) {
window.clearInterval(intervalId);

window.location.hash = popup.location.hash;



authContext.handleWindowCallback();
popup.close();
var user = authContext.getCachedUser();
if (user) {
console.log(JSON.stringify(user))
} else {
console.error(authContext.getLoginError());
}
}
} catch (whatever) {
if (popup.closed) {
console.error(whatever)
}
}
}, 100);
};


authContext.login();


authContext.acquireToken("https://graph.microsoft.com/", function() { console.log(arguments); debugger })

Frequently asked issues

Debugging and verification approach

You can’t verify your change until the production release, also the change for the production environment can’t be verified on other staging environment since they are using different hosts. So the question is how to debug or do verification?

Basically you can run a local server to host your application with adding a host record which points the production host to your local IP address like 127.0.0.1 to make it. Remember to enable HTTPS protocol for your local server.

And it’s better to verify your change on both common window and incognito window after the release.

Difference between access token, ID token, and refresh token

We observed that /oauth2/v2.0/token return 3 tokens: access_token, id_token and refresh_token.

access_token enables clients to securely call protected web APIs, and are used by web APIs to perform authentication and authorization. For more details please check Microsoft identity platform access tokens.

id_token should be used to validate that a user is who they claim to be and get additional useful information about them, it can be sent alongside or instead of an access token. We have not used it. For more details please check Microsoft identity platform ID tokens.

access_token and id_token are both JWT which consists of a header, payload, and signature portion, that’s why they look so similiar though these two strings are base64 encoded. We mainly use access token for the application, it contains more information than ID token, and we can get user info like name, E-mail from it.

Because access tokens are valid for only a short period of time, authorization servers will sometimes issue a refresh token at the same time the access token is issued. MSAL.js will exchange the refresh_token while request token silently for a new access token when needed.

How to change token expiration time?

Please check this answer from StackOverflow.

InteractionRequiredAuthError: AADSTS50058: A silent sign-in request was sent but no user is signed in.

This error need interaction sign in, thus catch the error and call acquireTokenRedirect method to sign in.

If the error message contains like this “The cookies used to represent the user’s session were not sent in the request to Azure AD. This could happen if the user is using Internet Explorer or Edge, and the web app sending the silent sign-in request is in different IE security zone than the Azure AD endpoint (login.microsoftonline.com).”, upgrade your MSAL.js v1.x to v2.x. Check more details here.

The frame attempting navigation of the top-level window is sandboxed, but the flag of ‘allow-top-navigation’ or ‘allow-top-navigation-by-user-activation’ is not set.

This error usually occurred while requesting token, mostly it’s caused by wrong reply URL which iframe could not load it to request token silently. So make sure your reply URL pointing to the blank static HTML resource is right. Additional, this error message is somehow confusing cause it does not tell the root cause directly, check more details here.

BrowserAuthError: pcke_not_created: The PCKE code challenge and verifier could not be generated.

Check the protocol and be sure it’s HTTPS.

References