fix: Azure single-tenant SSO tokens are unable to refresh (#5551)

This commit is contained in:
Tom Moor
2023-07-11 18:59:28 -04:00
committed by GitHub
parent 5ae4834333
commit c56add74c6
3 changed files with 42 additions and 6 deletions

View File

@@ -93,6 +93,7 @@ class UserAuthentication extends IdModel {
): Promise<boolean> { ): Promise<boolean> {
// Check a maximum of once every 5 minutes // Check a maximum of once every 5 minutes
if (this.lastValidatedAt > subMinutes(Date.now(), 5) && !force) { if (this.lastValidatedAt > subMinutes(Date.now(), 5) && !force) {
Logger.debug("utils", "Skipping access token validation");
return true; return true;
} }
@@ -158,7 +159,10 @@ class UserAuthentication extends IdModel {
const client = authenticationProvider.oauthClient; const client = authenticationProvider.oauthClient;
if (client) { if (client) {
const response = await client.rotateToken(this.refreshToken); const response = await client.rotateToken(
this.accessToken,
this.refreshToken
);
// Not all OAuth providers return a new refreshToken so we need to guard // Not all OAuth providers return a new refreshToken so we need to guard
// against setting to an empty value. // against setting to an empty value.

View File

@@ -1,9 +1,36 @@
import JWT from "jsonwebtoken";
import env from "@server/env";
import OAuthClient from "./oauth"; import OAuthClient from "./oauth";
type AzurePayload = {
/* A GUID that represents the Azure AD tenant that the user is from */
tid: string;
};
export default class AzureClient extends OAuthClient { export default class AzureClient extends OAuthClient {
endpoints = { endpoints = {
authorize: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", authorize: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
token: "https://login.microsoftonline.com/common/oauth2/v2.0/token", token: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
userinfo: "https://graph.microsoft.com/v1.0/me", userinfo: "https://graph.microsoft.com/v1.0/me",
}; };
async rotateToken(
accessToken: string,
refreshToken: string
): Promise<{
accessToken: string;
refreshToken?: string;
expiresAt: Date;
}> {
if (env.isCloudHosted()) {
return super.rotateToken(accessToken, refreshToken);
}
const payload = JWT.decode(accessToken) as AzurePayload;
return super.rotateToken(
accessToken,
refreshToken,
`https://login.microsoftonline.com/${payload.tid}/oauth2/v2.0/token`
);
}
} }

View File

@@ -1,4 +1,5 @@
import fetch from "fetch-with-proxy"; import fetch from "fetch-with-proxy";
import Logger from "@server/logging/Logger";
import { AuthenticationError, InvalidRequestError } from "../errors"; import { AuthenticationError, InvalidRequestError } from "../errors";
export default abstract class OAuthClient { export default abstract class OAuthClient {
@@ -41,18 +42,22 @@ export default abstract class OAuthClient {
return data; return data;
}; };
rotateToken = async ( async rotateToken(
refreshToken: string _accessToken: string,
refreshToken: string,
endpoint = this.endpoints.token
): Promise<{ ): Promise<{
accessToken: string; accessToken: string;
refreshToken?: string; refreshToken?: string;
expiresAt: Date; expiresAt: Date;
}> => { }> {
let data; let data;
let response; let response;
try { try {
response = await fetch(this.endpoints.token, { Logger.debug("utils", "Rotating token", { endpoint });
response = await fetch(endpoint, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
@@ -79,5 +84,5 @@ export default abstract class OAuthClient {
accessToken: data.access_token, accessToken: data.access_token,
expiresAt: new Date(Date.now() + data.expires_in * 1000), expiresAt: new Date(Date.now() + data.expires_in * 1000),
}; };
}; }
} }