feat(SSO): メールアドレスのnormalizeを設定可能にする (MisskeyIO#971)
This commit is contained in:
parent
17e14bb87e
commit
c94e5d7e22
9 changed files with 49 additions and 3 deletions
|
@ -0,0 +1,11 @@
|
||||||
|
export class SSOWantEmailAddressNormalized1745247339195 {
|
||||||
|
name = 'SSOWantEmailAddressNormalized1745247339195'
|
||||||
|
|
||||||
|
async up(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "sso_service_provider" ADD "wantEmailAddressNormalized" boolean NOT NULL DEFAULT true`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(queryRunner) {
|
||||||
|
await queryRunner.query(`ALTER TABLE "sso_service_provider" DROP COLUMN "wantEmailAddressNormalized"`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,4 +79,9 @@ export class MiSingleSignOnServiceProvider {
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
public wantAssertionsSigned: boolean;
|
public wantAssertionsSigned: boolean;
|
||||||
|
|
||||||
|
@Column('boolean', {
|
||||||
|
default: true,
|
||||||
|
})
|
||||||
|
public wantEmailAddressNormalized: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,10 @@ export const meta = {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
|
wantEmailAddressNormalized: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -101,6 +105,7 @@ export const paramDef = {
|
||||||
cipherAlgorithm: { type: 'string', nullable: true },
|
cipherAlgorithm: { type: 'string', nullable: true },
|
||||||
wantAuthnRequestsSigned: { type: 'boolean', nullable: false, default: false },
|
wantAuthnRequestsSigned: { type: 'boolean', nullable: false, default: false },
|
||||||
wantAssertionsSigned: { type: 'boolean', nullable: false, default: true },
|
wantAssertionsSigned: { type: 'boolean', nullable: false, default: true },
|
||||||
|
wantEmailAddressNormalized: { type: 'boolean', nullable: false, default: true },
|
||||||
useCertificate: { type: 'boolean', nullable: false, default: true },
|
useCertificate: { type: 'boolean', nullable: false, default: true },
|
||||||
secret: { type: 'string', nullable: true },
|
secret: { type: 'string', nullable: true },
|
||||||
},
|
},
|
||||||
|
@ -157,6 +162,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
cipherAlgorithm: ps.cipherAlgorithm ? ps.cipherAlgorithm : null,
|
cipherAlgorithm: ps.cipherAlgorithm ? ps.cipherAlgorithm : null,
|
||||||
wantAuthnRequestsSigned: ps.wantAuthnRequestsSigned,
|
wantAuthnRequestsSigned: ps.wantAuthnRequestsSigned,
|
||||||
wantAssertionsSigned: ps.wantAssertionsSigned,
|
wantAssertionsSigned: ps.wantAssertionsSigned,
|
||||||
|
wantEmailAddressNormalized: ps.wantEmailAddressNormalized,
|
||||||
}).then(r => this.singleSignOnServiceProviderRepository.findOneByOrFail({ id: r.identifiers[0].id }));
|
}).then(r => this.singleSignOnServiceProviderRepository.findOneByOrFail({ id: r.identifiers[0].id }));
|
||||||
|
|
||||||
this.moderationLogService.log(me, 'createSSOServiceProvider', {
|
this.moderationLogService.log(me, 'createSSOServiceProvider', {
|
||||||
|
@ -178,6 +184,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
cipherAlgorithm: ssoServiceProvider.cipherAlgorithm,
|
cipherAlgorithm: ssoServiceProvider.cipherAlgorithm,
|
||||||
wantAuthnRequestsSigned: ssoServiceProvider.wantAuthnRequestsSigned,
|
wantAuthnRequestsSigned: ssoServiceProvider.wantAuthnRequestsSigned,
|
||||||
wantAssertionsSigned: ssoServiceProvider.wantAssertionsSigned,
|
wantAssertionsSigned: ssoServiceProvider.wantAssertionsSigned,
|
||||||
|
wantEmailAddressNormalized: ssoServiceProvider.wantEmailAddressNormalized,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,10 @@ export const meta = {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
optional: false, nullable: false,
|
optional: false, nullable: false,
|
||||||
},
|
},
|
||||||
|
wantEmailAddressNormalized: {
|
||||||
|
type: 'boolean',
|
||||||
|
optional: false, nullable: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -116,6 +120,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
cipherAlgorithm: service.cipherAlgorithm,
|
cipherAlgorithm: service.cipherAlgorithm,
|
||||||
wantAuthnRequestsSigned: service.wantAuthnRequestsSigned,
|
wantAuthnRequestsSigned: service.wantAuthnRequestsSigned,
|
||||||
wantAssertionsSigned: service.wantAssertionsSigned,
|
wantAssertionsSigned: service.wantAssertionsSigned,
|
||||||
|
wantEmailAddressNormalized: service.wantEmailAddressNormalized,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ export const paramDef = {
|
||||||
cipherAlgorithm: { type: 'string', nullable: true },
|
cipherAlgorithm: { type: 'string', nullable: true },
|
||||||
wantAuthnRequestsSigned: { type: 'boolean', nullable: false },
|
wantAuthnRequestsSigned: { type: 'boolean', nullable: false },
|
||||||
wantAssertionsSigned: { type: 'boolean', nullable: false },
|
wantAssertionsSigned: { type: 'boolean', nullable: false },
|
||||||
|
wantEmailAddressNormalized: { type: 'boolean', nullable: false },
|
||||||
regenerateCertificate: { type: 'boolean', nullable: true },
|
regenerateCertificate: { type: 'boolean', nullable: true },
|
||||||
secret: { type: 'string', nullable: true },
|
secret: { type: 'string', nullable: true },
|
||||||
},
|
},
|
||||||
|
@ -92,6 +93,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
cipherAlgorithm: ps.cipherAlgorithm !== '' ? ps.cipherAlgorithm : null,
|
cipherAlgorithm: ps.cipherAlgorithm !== '' ? ps.cipherAlgorithm : null,
|
||||||
wantAuthnRequestsSigned: ps.wantAuthnRequestsSigned,
|
wantAuthnRequestsSigned: ps.wantAuthnRequestsSigned,
|
||||||
wantAssertionsSigned: ps.wantAssertionsSigned,
|
wantAssertionsSigned: ps.wantAssertionsSigned,
|
||||||
|
wantEmailAddressNormalized: ps.wantEmailAddressNormalized,
|
||||||
});
|
});
|
||||||
|
|
||||||
const updatedService = await this.singleSignOnServiceProviderRepository.findOneByOrFail({ id: service.id });
|
const updatedService = await this.singleSignOnServiceProviderRepository.findOneByOrFail({ id: service.id });
|
||||||
|
|
|
@ -180,7 +180,9 @@ export class JWTIdentifyProviderService {
|
||||||
preferred_username: user.username,
|
preferred_username: user.username,
|
||||||
profile: `${this.config.url}/@${user.username}`,
|
profile: `${this.config.url}/@${user.username}`,
|
||||||
picture: user.avatarUrl ?? undefined,
|
picture: user.avatarUrl ?? undefined,
|
||||||
email: profile.emailVerified ? normalizeEmailAddress(profile.email) : `${user.username}@${this.config.hostname}`,
|
email: profile.emailVerified
|
||||||
|
? (ssoServiceProvider.wantEmailAddressNormalized ? normalizeEmailAddress(profile.email) : profile.email)
|
||||||
|
: `${user.username}@users.${this.config.hostname}`,
|
||||||
email_verified: profile.emailVerified,
|
email_verified: profile.emailVerified,
|
||||||
mfa_enabled: profile.twoFactorEnabled,
|
mfa_enabled: profile.twoFactorEnabled,
|
||||||
updated_at: Math.floor((user.updatedAt?.getTime() ?? user.createdAt.getTime()) / 1000),
|
updated_at: Math.floor((user.updatedAt?.getTime() ?? user.createdAt.getTime()) / 1000),
|
||||||
|
|
|
@ -444,7 +444,9 @@ export class SAMLIdentifyProviderService {
|
||||||
'saml:Subject': {
|
'saml:Subject': {
|
||||||
'saml:NameID': {
|
'saml:NameID': {
|
||||||
'@Format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
'@Format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
||||||
'#text': profile.emailVerified ? normalizeEmailAddress(profile.email) : `${user.username}@${this.config.hostname}`,
|
'#text': profile.emailVerified
|
||||||
|
? (ssoServiceProvider.wantEmailAddressNormalized ? normalizeEmailAddress(profile.email) : profile.email)
|
||||||
|
: `${user.username}@users.${this.config.hostname}`,
|
||||||
},
|
},
|
||||||
'saml:SubjectConfirmation': {
|
'saml:SubjectConfirmation': {
|
||||||
'@Method': 'urn:oasis:names:tc:SAML:2.0:cm:bearer',
|
'@Method': 'urn:oasis:names:tc:SAML:2.0:cm:bearer',
|
||||||
|
@ -569,7 +571,9 @@ export class SAMLIdentifyProviderService {
|
||||||
'@NameFormat': 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
'@NameFormat': 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||||
'saml:AttributeValue': {
|
'saml:AttributeValue': {
|
||||||
'@xsi:type': 'xs:string',
|
'@xsi:type': 'xs:string',
|
||||||
'#text': profile.emailVerified ? normalizeEmailAddress(profile.email) : `${user.username}@${this.config.hostname}`,
|
'#text': profile.emailVerified
|
||||||
|
? (ssoServiceProvider.wantEmailAddressNormalized ? normalizeEmailAddress(profile.email) : profile.email)
|
||||||
|
: `${user.username}@users.${this.config.hostname}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -206,6 +206,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSwitch v-model="service.wantAssertionsSigned">
|
<MkSwitch v-model="service.wantAssertionsSigned">
|
||||||
<template #label>Want Assertions Signed</template>
|
<template #label>Want Assertions Signed</template>
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
|
<MkSwitch v-model="service.wantEmailAddressNormalized">
|
||||||
|
<template #label>Want Email Address Normalized</template>
|
||||||
|
</MkSwitch>
|
||||||
<MkSwitch v-model="service.useCertificate" :disabled="!!service.createdAt">
|
<MkSwitch v-model="service.useCertificate" :disabled="!!service.createdAt">
|
||||||
<template #label>Use Certificate</template>
|
<template #label>Use Certificate</template>
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
|
@ -422,6 +425,7 @@ function ssoServiceAddNew() {
|
||||||
cipherAlgorithm: '',
|
cipherAlgorithm: '',
|
||||||
wantAuthnRequestsSigned: false,
|
wantAuthnRequestsSigned: false,
|
||||||
wantAssertionsSigned: true,
|
wantAssertionsSigned: true,
|
||||||
|
wantEmailAddressNormalized: true,
|
||||||
regenerateCertificate: false,
|
regenerateCertificate: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -453,6 +457,7 @@ async function ssoServiceSave(service) {
|
||||||
cipherAlgorithm: service.cipherAlgorithm,
|
cipherAlgorithm: service.cipherAlgorithm,
|
||||||
wantAuthnRequestsSigned: service.wantAuthnRequestsSigned,
|
wantAuthnRequestsSigned: service.wantAuthnRequestsSigned,
|
||||||
wantAssertionsSigned: service.wantAssertionsSigned,
|
wantAssertionsSigned: service.wantAssertionsSigned,
|
||||||
|
wantEmailAddressNormalized: service.wantEmailAddressNormalized,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (service.createdAt !== undefined) {
|
if (service.createdAt !== undefined) {
|
||||||
|
|
|
@ -10972,6 +10972,8 @@ export type operations = {
|
||||||
/** @default true */
|
/** @default true */
|
||||||
wantAssertionsSigned?: boolean;
|
wantAssertionsSigned?: boolean;
|
||||||
/** @default true */
|
/** @default true */
|
||||||
|
wantEmailAddressNormalized?: boolean;
|
||||||
|
/** @default true */
|
||||||
useCertificate: boolean;
|
useCertificate: boolean;
|
||||||
secret?: string | null;
|
secret?: string | null;
|
||||||
};
|
};
|
||||||
|
@ -10998,6 +11000,7 @@ export type operations = {
|
||||||
cipherAlgorithm?: string | null;
|
cipherAlgorithm?: string | null;
|
||||||
wantAuthnRequestsSigned: boolean;
|
wantAuthnRequestsSigned: boolean;
|
||||||
wantAssertionsSigned: boolean;
|
wantAssertionsSigned: boolean;
|
||||||
|
wantEmailAddressNormalized: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -11123,6 +11126,7 @@ export type operations = {
|
||||||
cipherAlgorithm?: string | null;
|
cipherAlgorithm?: string | null;
|
||||||
wantAuthnRequestsSigned: boolean;
|
wantAuthnRequestsSigned: boolean;
|
||||||
wantAssertionsSigned: boolean;
|
wantAssertionsSigned: boolean;
|
||||||
|
wantEmailAddressNormalized: boolean;
|
||||||
})[];
|
})[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -11179,6 +11183,7 @@ export type operations = {
|
||||||
cipherAlgorithm?: string | null;
|
cipherAlgorithm?: string | null;
|
||||||
wantAuthnRequestsSigned?: boolean;
|
wantAuthnRequestsSigned?: boolean;
|
||||||
wantAssertionsSigned?: boolean;
|
wantAssertionsSigned?: boolean;
|
||||||
|
wantEmailAddressNormalized?: boolean;
|
||||||
regenerateCertificate?: boolean | null;
|
regenerateCertificate?: boolean | null;
|
||||||
secret?: string | null;
|
secret?: string | null;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue