Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@ production app.
`https://<tenant>.b2clogin.com/<tenant>.onmicrosoft.com/<policy>`. For Entra
External ID (CIAM) tenants the authority is typically just
`https://<tenant>.ciamlogin.com/`.
5. **Token configuration → Optional claims → ID** — add `login_hint` for the nrfCloud
SPA client. MSAL uses this claim as `logout_hint` so CIAM can end the server
session without showing “Pick an account” (especially after myNordic portal SSO).
6. **Authentication → Redirect URI** — register the SPA **logout** URL (e.g.
`http://localhost:8080/` or your nrfCloud origin) as a front-channel logout /
post-logout redirect URI, matching `postLogoutRedirectUri` in `msalConfig.js`.

### Logout after myNordic portal SSO (nrfCloud)

If users sign in on myNordic and land in nrfCloud via `login_hint` / silent SSO,
then log out from nrfCloud and CIAM shows **“Pick an account”** with **no accounts
listed**, the logout request did not identify the CIAM session. Typical causes:

| Cause | Fix |
| ----- | --- |
| `logoutRedirect()` called with no `account` | Pass `msal.getAllAccounts()[0]` (or the active account). |
| No `logout_hint` on the end-session URL | Pass `logoutHint` (email from myNordic `login_hint`, or `account.idTokenClaims.login_hint`). |
| `login_hint` not in the ID token | Enable the optional claim on the **nrfCloud** app registration (see checklist item 5). |
| Missing post-logout redirect | Set `postLogoutRedirectUri` in MSAL config and register it in Azure. |

The `mynordic-oauth-test` harness persists `login_hint` from the portal redirect
and sends it on logout. Mirror that in nrfCloud production code.

## 1 — Scaffold the test SPA

Expand Down
14 changes: 12 additions & 2 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,18 @@ document.getElementById("portal-login").addEventListener("click", () => {
window.location.href = portalSignUpUrl.toString();
});

document.getElementById("logout").addEventListener("click", () => {
msal.logoutRedirect();
document.getElementById("logout").addEventListener("click", async () => {
const account = msal.getAllAccounts()[0];
const logoutHint =
account?.idTokenClaims?.login_hint ?? account?.username ?? undefined;

const request = {
postLogoutRedirectUri: msalConfig.auth.postLogoutRedirectUri,
};
if (account) request.account = account;
if (logoutHint) request.logoutHint = logoutHint;

await msal.logoutRedirect(request);
});

init();
4 changes: 3 additions & 1 deletion msalConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ const authority = B2C_AUTHORITY;
const clientId = B2C_CLIENT_ID;

const authorityHost = new URL(authority).hostname;
const appOrigin = "http://localhost:8080";

export const msalConfig = {
auth: {
clientId,
authority,
redirectUri: "http://localhost:8080/mynordic/callback",
redirectUri: `${appOrigin}/mynordic/callback`,
postLogoutRedirectUri: `${appOrigin}/`,
knownAuthorities: [authorityHost],
},
cache: {
Expand Down
17 changes: 17 additions & 0 deletions mynordic-oauth-test/.envrc

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not commit secrets to source code. Add .envrc to your global gitignore file.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# PROD ENV
export B2C_AUTHORITY="https://nordicsemiextprod.ciamlogin.com/"
export B2C_CLIENT_ID="7e241ef6-76de-4cc5-9f52-298222874afb"

# DEV ENV
# export B2C_AUTHORITY="https://nordicsemiextdev.ciamlogin.com/"
# export B2C_CLIENT_ID="dd47d209-3cd3-4e75-86e5-d419ea0cdd05"

# TEST USER
# export TEST_USER_EMAIL="jay.manuel+v5001NrfDev@nordicsemi.no"
# export TEST_USER_PASSWORD="Test@123"

# export TEST_USER_EMAIL="akhila.veetil@nordicsemi.no"
# export TEST_USER_PASSWORD="Test@123"

export TEST_USER_EMAIL="aallan.allanigue+dev@nordicsemi.no"
export TEST_USER_PASSWORD="A@11anigue"
1 change: 1 addition & 0 deletions mynordic-oauth-test/dist/assets/Configuration-DmI3R7F5.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions mynordic-oauth-test/dist/assets/main-BeSCdD2b.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions mynordic-oauth-test/dist/assets/sso-CFKbQoP1.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions mynordic-oauth-test/dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>nrfCloud</title>
<script type="module" crossorigin src="/assets/Configuration-DmI3R7F5.js"></script>
<script type="module" crossorigin src="/assets/main-BeSCdD2b.js"></script>
</head>
<body>
<h1>nrfCloud — Silent SSO receiver</h1>
<p>
After myNordic CIAM login, users are redirected to
<code>/mynordic/from-portal?login_hint=…</code> where this app runs
<code>ssoSilent</code> with that <code>login_hint</code>.
</p>
<button id="login">Log in interactively</button>
<button id="logout" hidden>Log out</button>
<pre id="output">Not authenticated.</pre>
</body>
</html>
16 changes: 16 additions & 0 deletions mynordic-oauth-test/dist/mynordic/from-portal/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>nrfCloud — Sign-in</title>
<script type="module" crossorigin src="/assets/Configuration-DmI3R7F5.js"></script>
<script type="module" crossorigin src="/assets/main-BeSCdD2b.js"></script>
</head>
<body>
<h1>nrfCloud</h1>
<p>Completing sign-in from myNordic…</p>
<button id="login" hidden>Log in</button>
<button id="logout" hidden>Log out</button>
<pre id="output">Signing in…</pre>
</body>
</html>
12 changes: 12 additions & 0 deletions mynordic-oauth-test/dist/mynordic/sso.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>SSO</title>
<script type="module" crossorigin src="/assets/sso-CFKbQoP1.js"></script>
<link rel="modulepreload" crossorigin href="/assets/Configuration-DmI3R7F5.js">
</head>
<body>
<p>Processing authentication…</p>
</body>
</html>
19 changes: 19 additions & 0 deletions mynordic-oauth-test/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>nrfCloud</title>
</head>
<body>
<h1>nrfCloud — Silent SSO receiver</h1>
<p>
After myNordic CIAM login, users are redirected to
<code>/mynordic/from-portal?login_hint=…</code> where this app runs
<code>ssoSilent</code> with that <code>login_hint</code>.
</p>
<button id="login">Log in interactively</button>
<button id="logout" hidden>Log out</button>
<pre id="output">Not authenticated.</pre>
<script type="module" src="/main.js"></script>
</body>
</html>
Loading