mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-07 22:49:26 +08:00
* feat(auth): init auth package & collection * feat(auth): register * feat(auth): use authenticator * feat(auth): mapRoles * feat(auth): refactor * feat(auth): base auth class * feat(auth): add plugin * chore(auth): test * chore(auth): add test cases * feat(auth): authenticators pane * chore(auth): custom hook useAuthTypes * feat(auth): authenticator pane * chore(auth): store options schema using context * feat(auth): signInPage provider * feat(auth): signUpPage provider * chore(auth): solve build errors * chore(auth): add dependency * chore(auth): remove dependency cycles * chore(auth): add plugin-auth to preset * chore(auth): fix test * feat(auth): authenticator enable status * fix(test): fix test using new authentication * feat(auth): migration, set up basic auth * chore(auth): can set options ui by component * fix(test): workflow manunal.test * fix(test): typo * feat(auth): support multi-language * chore(auth): imporve code * chore(auth): hide button if no configuration * chore(auth): readme * chore(auth): remove allowSignup prop * chore(auth): move configure pane to edit form * fix(auth): jwt options bug * feat(auth): init sms-auth * chore(auth): at least authenticator required * chore(auth): add test * feat(auth): support sms auth * fix(auth): fix test * chore(auth): move findOrCreateUser to AuthModel * chore(auth): history compatible processing * feat(auth): support SAML auth * chore(auth): saml auth list * chore(saml-auth): improve ui * Merge branch 'main' into feat/authentication * chore(auth): improve code * fix(saml-auth): fix bug * fix(saml-auth): fix saml options * chore(saml-auth): compatible processing && ut * fix(auth): signin page bug * chore(auth): saml compatible processing * feat(auth): oidc-auth * fix(oidc-auth): bug * fix(oidc-auth): bug * fix(auth): fix test * chore(auth): filter enabled authenticator * chore(oidc): add field map * chore(auth): update readme * docs(auth): create sms-auth readme * feat(auth): allow signup config * test(auth): fix test * feat(auth): allow saml and oidc use http * chore(oidc-auth): extends timeout * docs(auth): update readme * feat(auth): support sort * docs(saml): update readme * feat(auth): support sort all authenticator * Merge branch 'main' into feat/authentication * Merge branch 'main' into feat/authentication * feat: improve code * docs(auth): add doc * Merge branch 'main' into feat/authentication * chore: update yarn.lock * feat: improve code * chore(acl): write role to acl if it exists in database and not found … (#2001) * chore(acl): write role to acl if it exists in database and not found in acl * fix: test * fix: eager load with nested association (#2002) * chore: upgrade vitest * chore: edit * refactor: auth class * fix: set options * chore(acl): write role to acl if it exists in database and not found … (#2001) * chore(acl): write role to acl if it exists in database and not found in acl * fix: test * fix: eager load with nested association (#2002) * chore: upgrade vitest * chore: add migrations * test: fix api-client test * chore: add sms-auth * feat: avoid no permission after auth type disabled * fix: translation --------- Co-authored-by: chenos <chenlinxh@gmail.com>
76 lines
2.1 KiB
TypeScript
76 lines
2.1 KiB
TypeScript
import { AuthConfig, BaseAuth } from '@nocobase/auth';
|
|
import { SAML, SamlConfig } from '@node-saml/node-saml';
|
|
|
|
interface SAMLOptions {
|
|
ssoUrl?: string;
|
|
certificate?: string;
|
|
idpIssuer?: string;
|
|
http?: boolean;
|
|
}
|
|
|
|
export class SAMLAuth extends BaseAuth {
|
|
constructor(config: AuthConfig) {
|
|
const { ctx } = config;
|
|
super({
|
|
...config,
|
|
userCollection: ctx.db.getCollection('users'),
|
|
});
|
|
}
|
|
|
|
getOptions() {
|
|
const ctx = this.ctx;
|
|
const { ssoUrl, certificate, idpIssuer, http }: SAMLOptions = this.options?.saml || {};
|
|
const name = this.authenticator.get('name');
|
|
const protocol = http ? 'http' : 'https';
|
|
return {
|
|
callbackUrl: `${protocol}://${ctx.host}/api/saml:redirect?authenticator=${name}`,
|
|
entryPoint: ssoUrl,
|
|
issuer: name,
|
|
cert: certificate,
|
|
idpIssuer,
|
|
wantAssertionsSigned: false,
|
|
} as SamlConfig;
|
|
}
|
|
|
|
async validate() {
|
|
const ctx = this.ctx;
|
|
const {
|
|
params: {
|
|
values: { samlResponse },
|
|
},
|
|
} = ctx.action;
|
|
const saml = new SAML(this.getOptions());
|
|
|
|
const { profile } = await saml.validatePostResponseAsync(samlResponse);
|
|
|
|
const { nameID, nickname, username, email, firstName, lastName, phone } = profile as Record<string, string>;
|
|
|
|
const fullName = firstName && lastName && `${firstName} ${lastName}`;
|
|
const name = nickname ?? username ?? fullName ?? nameID;
|
|
|
|
// Compatible processing
|
|
// When email is provided or nameID is email, use email to find user
|
|
// If found, associate the user with the current authenticator
|
|
if (email || nameID.match(/^.+@.+\..+$/)) {
|
|
const userRepo = this.userCollection.repository;
|
|
const user = await userRepo.findOne({
|
|
filter: { email: email || nameID },
|
|
});
|
|
if (user) {
|
|
await this.authenticator.addUser(user, {
|
|
through: {
|
|
uuid: nameID,
|
|
},
|
|
});
|
|
return user;
|
|
}
|
|
}
|
|
|
|
return await this.authenticator.findOrCreateUser(nameID, {
|
|
nickname: name,
|
|
email: email ?? null,
|
|
phone: phone ?? null,
|
|
});
|
|
}
|
|
}
|