1
0
mirror of https://github.com/stonith404/pingvin-share.git synced 2024-11-16 12:20:13 +01:00

feat(oauth): add oidc username claim (#357)

* feat(oauth): add oidc username claim

* style: remove undefined
This commit is contained in:
Qing Fu 2023-12-20 19:32:42 +08:00 committed by GitHub
parent f179189b59
commit 3ea52a24ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 11 deletions

View File

@ -201,6 +201,10 @@ const configVariables: ConfigVariables = {
type: "string", type: "string",
defaultValue: "", defaultValue: "",
}, },
"oidc-usernameClaim": {
type: "string",
defaultValue: "",
},
"oidc-clientId": { "oidc-clientId": {
type: "string", type: "string",
defaultValue: "", defaultValue: "",

View File

@ -108,6 +108,7 @@ export abstract class GenericOidcProvider implements OAuthProvider<OidcToken> {
async getUserInfo( async getUserInfo(
token: OAuthToken<OidcToken>, token: OAuthToken<OidcToken>,
query: OAuthCallbackDto, query: OAuthCallbackDto,
claim?: string
): Promise<OAuthSignInDto> { ): Promise<OAuthSignInDto> {
const idTokenData = this.decodeIdToken(token.idToken); const idTokenData = this.decodeIdToken(token.idToken);
// maybe it's not necessary to verify the id token since it's directly obtained from the provider // maybe it's not necessary to verify the id token since it's directly obtained from the provider
@ -122,11 +123,30 @@ export abstract class GenericOidcProvider implements OAuthProvider<OidcToken> {
throw new ErrorPageException("invalid_token"); throw new ErrorPageException("invalid_token");
} }
const username = claim
? idTokenData[claim]
: idTokenData.name ||
idTokenData.nickname ||
idTokenData.preferred_username;
if (!username) {
this.logger.error(
`Can not get username from ID Token ${JSON.stringify(
idTokenData,
undefined,
2,
)}`,
);
throw new ErrorPageException("cannot_get_user_info", undefined, [
`provider_${this.name}`,
]);
}
return { return {
provider: this.name as any, provider: this.name as any,
email: idTokenData.email, email: idTokenData.email,
providerId: idTokenData.sub, providerId: idTokenData.sub,
providerUsername: idTokenData.name, providerUsername: username,
}; };
} }
@ -211,5 +231,7 @@ export interface OidcIdToken {
iat: number; iat: number;
email: string; email: string;
name: string; name: string;
nickname: string;
preferred_username: string;
nonce: string; nonce: string;
} }

View File

@ -1,9 +1,12 @@
import { GenericOidcProvider } from "./genericOidc.provider"; import { GenericOidcProvider, OidcToken } from "./genericOidc.provider";
import { Inject, Injectable } from "@nestjs/common"; import { Inject, Injectable } from "@nestjs/common";
import { ConfigService } from "../../config/config.service"; import { ConfigService } from "../../config/config.service";
import { JwtService } from "@nestjs/jwt"; import { JwtService } from "@nestjs/jwt";
import { CACHE_MANAGER } from "@nestjs/cache-manager"; import { CACHE_MANAGER } from "@nestjs/cache-manager";
import { Cache } from "cache-manager"; import { Cache } from "cache-manager";
import { OAuthCallbackDto } from "../dto/oauthCallback.dto";
import { OAuthSignInDto } from "../dto/oauthSignIn.dto";
import { OAuthToken } from "./oauthProvider.interface";
@Injectable() @Injectable()
export class OidcProvider extends GenericOidcProvider { export class OidcProvider extends GenericOidcProvider {
@ -24,4 +27,13 @@ export class OidcProvider extends GenericOidcProvider {
protected getDiscoveryUri(): string { protected getDiscoveryUri(): string {
return this.config.get("oauth.oidc-discoveryUri"); return this.config.get("oauth.oidc-discoveryUri");
} }
getUserInfo(
token: OAuthToken<OidcToken>,
query: OAuthCallbackDto,
_?: string,
): Promise<OAuthSignInDto> {
const claim = this.config.get("oauth.oidc-usernameClaim") || undefined;
return super.getUserInfo(token, query, claim);
}
} }

View File

@ -478,14 +478,16 @@ export default {
"admin.config.oauth.discord-client-id.description": "Client ID of the Discord OAuth app", "admin.config.oauth.discord-client-id.description": "Client ID of the Discord OAuth app",
"admin.config.oauth.discord-client-secret": "Discord Client secret", "admin.config.oauth.discord-client-secret": "Discord Client secret",
"admin.config.oauth.discord-client-secret.description": "Client secret of the Discord OAuth app", "admin.config.oauth.discord-client-secret.description": "Client secret of the Discord OAuth app",
"admin.config.oauth.oidc-enabled": "OpenID", "admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description": "Whether OpenID login is enabled", "admin.config.oauth.oidc-enabled.description": "Whether OpenID Connect login is enabled",
"admin.config.oauth.oidc-discovery-uri": "OpenID Discovery URI", "admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri.description": "Discovery URI of the OpenID OAuth app", "admin.config.oauth.oidc-discovery-uri.description": "Discovery URI of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-client-id": "OpenID Client ID", "admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
"admin.config.oauth.oidc-client-id.description": "Client ID of the OpenID OAuth app", "admin.config.oauth.oidc-username-claim.description": "Username claim in OpenID Connect ID token. Leave it blank if you don't know what this config is.",
"admin.config.oauth.oidc-client-secret": "OpenID Client secret", "admin.config.oauth.oidc-client-id": "OpenID Connect Client ID",
"admin.config.oauth.oidc-client-secret.description": "Client secret of the OpenID OAuth app", "admin.config.oauth.oidc-client-id.description": "Client ID of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-client-secret": "OpenID Connect Client secret",
"admin.config.oauth.oidc-client-secret.description": "Client secret of the OpenID Connect OAuth app",
// 404 // 404
"404.description": "Oops this page doesn't exist.", "404.description": "Oops this page doesn't exist.",
@ -505,11 +507,12 @@ export default {
"error.msg.not_linked": "This {0} account haven't linked to any account yet.", "error.msg.not_linked": "This {0} account haven't linked to any account yet.",
"error.msg.unverified_account": "This {0} account is unverified, please try again after verification.", "error.msg.unverified_account": "This {0} account is unverified, please try again after verification.",
"error.msg.discord_guild_permission_denied": "You are not allowed to sign in.", "error.msg.discord_guild_permission_denied": "You are not allowed to sign in.",
"error.msg.cannot_get_user_info": "Can not get your user info from this {0} account.",
"error.param.provider_github": "GitHub", "error.param.provider_github": "GitHub",
"error.param.provider_google": "Google", "error.param.provider_google": "Google",
"error.param.provider_microsoft": "Microsoft", "error.param.provider_microsoft": "Microsoft",
"error.param.provider_discord": "Discord", "error.param.provider_discord": "Discord",
"error.param.provider_oidc": "OpenID", "error.param.provider_oidc": "OpenID Connect",
// Common translations // Common translations
"common.button.save": "Save", "common.button.save": "Save",