From 2816946c94d1ecb7b1a485c4799b4ec988b68d15 Mon Sep 17 00:00:00 2001 From: Lurkars Date: Wed, 16 Feb 2022 09:11:08 +0100 Subject: [PATCH 1/2] add OIDC username + locale --- docker-compose.single-domain.yaml | 3 ++ docker-compose.yaml | 3 ++ front/src/Connexion/ConnectionManager.ts | 34 +++++++++++++++++-- .../src/Controller/AuthenticateController.ts | 21 ++++++++++-- pusher/src/Enum/EnvironmentVariable.ts | 3 ++ pusher/src/Services/JWTTokenManager.ts | 6 ++-- pusher/src/Services/OpenIDClient.ts | 12 +++++-- 7 files changed, 72 insertions(+), 10 deletions(-) diff --git a/docker-compose.single-domain.yaml b/docker-compose.single-domain.yaml index 1612e396..5972df58 100644 --- a/docker-compose.single-domain.yaml +++ b/docker-compose.single-domain.yaml @@ -76,6 +76,9 @@ services: OPID_CLIENT_ISSUER: $OPID_CLIENT_ISSUER OPID_CLIENT_REDIRECT_URL: $OPID_CLIENT_REDIRECT_URL OPID_PROFILE_SCREEN_PROVIDER: $OPID_PROFILE_SCREEN_PROVIDER + OPID_ADDITIONAL_SCOPES: $OPID_ADDITIONAL_SCOPES + OPID_USERNAME_CLAIM: $OPID_USERNAME_CLAIM + OPID_LOCALE_CLAIM: $OPID_LOCALE_CLAIM DISABLE_ANONYMOUS: $DISABLE_ANONYMOUS volumes: - ./pusher:/usr/src/app diff --git a/docker-compose.yaml b/docker-compose.yaml index 8489b336..eb610122 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -86,6 +86,9 @@ services: OPID_CLIENT_ISSUER: $OPID_CLIENT_ISSUER OPID_CLIENT_REDIRECT_URL: $OPID_CLIENT_REDIRECT_URL OPID_PROFILE_SCREEN_PROVIDER: $OPID_PROFILE_SCREEN_PROVIDER + OPID_ADDITIONAL_SCOPES: $OPID_ADDITIONAL_SCOPES + OPID_USERNAME_CLAIM: $OPID_USERNAME_CLAIM + OPID_LOCALE_CLAIM: $OPID_LOCALE_CLAIM DISABLE_ANONYMOUS: $DISABLE_ANONYMOUS volumes: - ./pusher:/usr/src/app diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index 05d0255d..62daa58d 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -16,6 +16,10 @@ import { isRegisterData } from "../Messages/JsonMessages/RegisterData"; import { isAdminApiData } from "../Messages/JsonMessages/AdminApiData"; import { limitMapStore } from "../Stores/GameStore"; import { showLimitRoomModalStore } from "../Stores/ModalStore"; +import { gameManager } from "../Phaser/Game/GameManager"; +import { locales } from "../i18n/i18n-util"; +import type { Locales } from "../i18n/i18n-types"; +import { setCurrentLocale } from "../i18n/locales"; class ConnectionManager { private localUser!: LocalUser; @@ -342,9 +346,12 @@ class ConnectionManager { throw new Error("No Auth code provided"); } } - const { authToken, userUuid, textures, email } = await Axios.get(`${PUSHER_URL}/login-callback`, { - params: { code, nonce, token, playUri: this.currentRoom?.key }, - }).then((res) => { + const { authToken, userUuid, textures, email, username, locale } = await Axios.get( + `${PUSHER_URL}/login-callback`, + { + params: { code, nonce, token, playUri: this.currentRoom?.key }, + } + ).then((res) => { return res.data; }); localUserStore.setAuthToken(authToken); @@ -352,6 +359,27 @@ class ConnectionManager { localUserStore.saveUser(this.localUser); this.authToken = authToken; + if (username) { + gameManager.setPlayerName(username); + } + + if (locale) { + try { + if (locales.indexOf(locale) == -1) { + locales.forEach((l) => { + if (l.startsWith(locale.split("-")[0])) { + setCurrentLocale(l); + return; + } + }); + } else { + setCurrentLocale(locale as Locales); + } + } catch (err) { + console.warn("Could not set locale", err); + } + } + //user connected, set connected store for menu at true userIsConnected.set(true); } diff --git a/pusher/src/Controller/AuthenticateController.ts b/pusher/src/Controller/AuthenticateController.ts index 89d3adf3..6abb94f8 100644 --- a/pusher/src/Controller/AuthenticateController.ts +++ b/pusher/src/Controller/AuthenticateController.ts @@ -93,7 +93,15 @@ export class AuthenticateController extends BaseController { res.writeStatus("200"); this.addCorsHeaders(res); res.writeHeader("Content-Type", "application/json"); - return res.end(JSON.stringify({ ...resCheckTokenAuth, ...resUserData, authToken: token })); + return res.end( + JSON.stringify({ + ...resCheckTokenAuth, + ...resUserData, + authToken: token, + username: authTokenData?.username, + locale: authTokenData?.locale, + }) + ); } catch (err) { console.info("User was not connected", err); } @@ -115,7 +123,12 @@ export class AuthenticateController extends BaseController { if (!email) { throw new Error("No email in the response"); } - const authToken = jwtTokenManager.createAuthToken(email, userInfo?.access_token); + const authToken = jwtTokenManager.createAuthToken( + email, + userInfo?.access_token, + userInfo?.username, + userInfo?.locale + ); //Get user data from Admin Back Office //This is very important to create User Local in LocalStorage in WorkAdventure @@ -124,7 +137,9 @@ export class AuthenticateController extends BaseController { res.writeStatus("200"); this.addCorsHeaders(res); res.writeHeader("Content-Type", "application/json"); - return res.end(JSON.stringify({ ...data, authToken })); + return res.end( + JSON.stringify({ ...data, authToken, username: userInfo?.username, locale: userInfo?.locale }) + ); } catch (e) { console.error("openIDCallback => ERROR", e); return this.errorToResponse(e, res); diff --git a/pusher/src/Enum/EnvironmentVariable.ts b/pusher/src/Enum/EnvironmentVariable.ts index b3415a82..347049b2 100644 --- a/pusher/src/Enum/EnvironmentVariable.ts +++ b/pusher/src/Enum/EnvironmentVariable.ts @@ -18,6 +18,9 @@ export const OPID_CLIENT_SECRET = process.env.OPID_CLIENT_SECRET || ""; export const OPID_CLIENT_ISSUER = process.env.OPID_CLIENT_ISSUER || ""; export const OPID_CLIENT_REDIRECT_URL = process.env.OPID_CLIENT_REDIRECT_URL || FRONT_URL + "/jwt"; export const OPID_PROFILE_SCREEN_PROVIDER = process.env.OPID_PROFILE_SCREEN_PROVIDER || ADMIN_URL + "/profile"; +export const OPID_ADDITIONAL_SCOPES = process.env.OPID_ADDITIONAL_SCOPES || ""; +export const OPID_USERNAME_CLAIM = process.env.OPID_USERNAME_CLAIM || "username"; +export const OPID_LOCALE_CLAIM = process.env.OPID_LOCALE_CLAIM || "locale"; export const DISABLE_ANONYMOUS: boolean = process.env.DISABLE_ANONYMOUS === "true"; export { diff --git a/pusher/src/Services/JWTTokenManager.ts b/pusher/src/Services/JWTTokenManager.ts index 4c094072..325df2d8 100644 --- a/pusher/src/Services/JWTTokenManager.ts +++ b/pusher/src/Services/JWTTokenManager.ts @@ -5,6 +5,8 @@ import { InvalidTokenError } from "../Controller/InvalidTokenError"; export interface AuthTokenData { identifier: string; //will be a email if logged in or an uuid if anonymous accessToken?: string; + username?: string; + locale?: string; } export interface AdminSocketTokenData { authorizedRoomIds: string[]; //the list of rooms the client is authorized to read from. @@ -16,8 +18,8 @@ class JWTTokenManager { return Jwt.verify(token, ADMIN_SOCKETS_TOKEN) as AdminSocketTokenData; } - public createAuthToken(identifier: string, accessToken?: string) { - return Jwt.sign({ identifier, accessToken }, SECRET_KEY, { expiresIn: "30d" }); + public createAuthToken(identifier: string, accessToken?: string, username?: string, locale?: string) { + return Jwt.sign({ identifier, accessToken, username, locale }, SECRET_KEY, { expiresIn: "30d" }); } public verifyJWTToken(token: string, ignoreExpiration: boolean = false): AuthTokenData { diff --git a/pusher/src/Services/OpenIDClient.ts b/pusher/src/Services/OpenIDClient.ts index 13bf6f76..4f600fc5 100644 --- a/pusher/src/Services/OpenIDClient.ts +++ b/pusher/src/Services/OpenIDClient.ts @@ -4,6 +4,9 @@ import { OPID_CLIENT_SECRET, OPID_CLIENT_ISSUER, OPID_CLIENT_REDIRECT_URL, + OPID_USERNAME_CLAIM, + OPID_LOCALE_CLAIM, + OPID_ADDITIONAL_SCOPES, } from "../Enum/EnvironmentVariable"; class OpenIDClient { @@ -26,7 +29,7 @@ class OpenIDClient { public authorizationUrl(state: string, nonce: string, playUri?: string, redirect?: string) { return this.initClient().then((client) => { return client.authorizationUrl({ - scope: "openid email", + scope: "openid email " + OPID_ADDITIONAL_SCOPES, prompt: "login", state: state, nonce: nonce, @@ -36,7 +39,10 @@ class OpenIDClient { }); } - public getUserInfo(code: string, nonce: string): Promise<{ email: string; sub: string; access_token: string }> { + public getUserInfo( + code: string, + nonce: string + ): Promise<{ email: string; sub: string; access_token: string; username: string; locale: string }> { return this.initClient().then((client) => { return client.callback(OPID_CLIENT_REDIRECT_URL, { code }, { nonce }).then((tokenSet) => { return client.userinfo(tokenSet).then((res) => { @@ -45,6 +51,8 @@ class OpenIDClient { email: res.email as string, sub: res.sub, access_token: tokenSet.access_token as string, + username: res[OPID_USERNAME_CLAIM] as string, + locale: res[OPID_LOCALE_CLAIM] as string, }; }); }); From c8047bf4fa6b600ef33f88415869ba572e2a3f7b Mon Sep 17 00:00:00 2001 From: Lurkars Date: Mon, 28 Feb 2022 12:09:33 +0100 Subject: [PATCH 2/2] change to scope variable in enviroment --- docker-compose.single-domain.yaml | 2 +- docker-compose.yaml | 2 +- pusher/src/Enum/EnvironmentVariable.ts | 2 +- pusher/src/Services/OpenIDClient.ts | 7 +++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docker-compose.single-domain.yaml b/docker-compose.single-domain.yaml index 5972df58..b9149ba0 100644 --- a/docker-compose.single-domain.yaml +++ b/docker-compose.single-domain.yaml @@ -76,7 +76,7 @@ services: OPID_CLIENT_ISSUER: $OPID_CLIENT_ISSUER OPID_CLIENT_REDIRECT_URL: $OPID_CLIENT_REDIRECT_URL OPID_PROFILE_SCREEN_PROVIDER: $OPID_PROFILE_SCREEN_PROVIDER - OPID_ADDITIONAL_SCOPES: $OPID_ADDITIONAL_SCOPES + OPID_SCOPE: $OPID_SCOPE OPID_USERNAME_CLAIM: $OPID_USERNAME_CLAIM OPID_LOCALE_CLAIM: $OPID_LOCALE_CLAIM DISABLE_ANONYMOUS: $DISABLE_ANONYMOUS diff --git a/docker-compose.yaml b/docker-compose.yaml index 68ee2c3b..3c16ce00 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -85,7 +85,7 @@ services: OPID_CLIENT_ISSUER: $OPID_CLIENT_ISSUER OPID_CLIENT_REDIRECT_URL: $OPID_CLIENT_REDIRECT_URL OPID_PROFILE_SCREEN_PROVIDER: $OPID_PROFILE_SCREEN_PROVIDER - OPID_ADDITIONAL_SCOPES: $OPID_ADDITIONAL_SCOPES + OPID_SCOPE: $OPID_SCOPE OPID_USERNAME_CLAIM: $OPID_USERNAME_CLAIM OPID_LOCALE_CLAIM: $OPID_LOCALE_CLAIM DISABLE_ANONYMOUS: $DISABLE_ANONYMOUS diff --git a/pusher/src/Enum/EnvironmentVariable.ts b/pusher/src/Enum/EnvironmentVariable.ts index 347049b2..c0d33894 100644 --- a/pusher/src/Enum/EnvironmentVariable.ts +++ b/pusher/src/Enum/EnvironmentVariable.ts @@ -18,7 +18,7 @@ export const OPID_CLIENT_SECRET = process.env.OPID_CLIENT_SECRET || ""; export const OPID_CLIENT_ISSUER = process.env.OPID_CLIENT_ISSUER || ""; export const OPID_CLIENT_REDIRECT_URL = process.env.OPID_CLIENT_REDIRECT_URL || FRONT_URL + "/jwt"; export const OPID_PROFILE_SCREEN_PROVIDER = process.env.OPID_PROFILE_SCREEN_PROVIDER || ADMIN_URL + "/profile"; -export const OPID_ADDITIONAL_SCOPES = process.env.OPID_ADDITIONAL_SCOPES || ""; +export const OPID_SCOPE = process.env.OPID_SCOPE || "openid email"; export const OPID_USERNAME_CLAIM = process.env.OPID_USERNAME_CLAIM || "username"; export const OPID_LOCALE_CLAIM = process.env.OPID_LOCALE_CLAIM || "locale"; export const DISABLE_ANONYMOUS: boolean = process.env.DISABLE_ANONYMOUS === "true"; diff --git a/pusher/src/Services/OpenIDClient.ts b/pusher/src/Services/OpenIDClient.ts index 4f600fc5..32bda560 100644 --- a/pusher/src/Services/OpenIDClient.ts +++ b/pusher/src/Services/OpenIDClient.ts @@ -6,7 +6,7 @@ import { OPID_CLIENT_REDIRECT_URL, OPID_USERNAME_CLAIM, OPID_LOCALE_CLAIM, - OPID_ADDITIONAL_SCOPES, + OPID_SCOPE, } from "../Enum/EnvironmentVariable"; class OpenIDClient { @@ -28,8 +28,11 @@ class OpenIDClient { public authorizationUrl(state: string, nonce: string, playUri?: string, redirect?: string) { return this.initClient().then((client) => { + if (!OPID_SCOPE.includes("email") || !OPID_SCOPE.includes("openid")) { + throw new Error("Invalid scope, 'email' and 'openid' are required in OPID_SCOPE."); + } return client.authorizationUrl({ - scope: "openid email " + OPID_ADDITIONAL_SCOPES, + scope: OPID_SCOPE, prompt: "login", state: state, nonce: nonce,