feat(SSO): JWTやSAMLでのSingle Sign-Onの実装 (MisskeyIO#519)

This commit is contained in:
まっちゃとーにゅ 2024-03-15 01:30:56 +09:00 committed by GitHub
parent d300a6829f
commit 8c1db331e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 4094 additions and 1725 deletions

View file

@ -343,6 +343,24 @@ type AdminShowUsersRequest = operations['admin/show-users']['requestBody']['cont
// @public (undocumented)
type AdminShowUsersResponse = operations['admin/show-users']['responses']['200']['content']['application/json'];
// @public (undocumented)
type AdminSsoCreateRequest = operations['admin/sso/create']['requestBody']['content']['application/json'];
// @public (undocumented)
type AdminSsoCreateResponse = operations['admin/sso/create']['responses']['200']['content']['application/json'];
// @public (undocumented)
type AdminSsoDeleteRequest = operations['admin/sso/delete']['requestBody']['content']['application/json'];
// @public (undocumented)
type AdminSsoListRequest = operations['admin/sso/list']['requestBody']['content']['application/json'];
// @public (undocumented)
type AdminSsoListResponse = operations['admin/sso/list']['responses']['200']['content']['application/json'];
// @public (undocumented)
type AdminSsoUpdateRequest = operations['admin/sso/update']['requestBody']['content']['application/json'];
// @public (undocumented)
type AdminSuspendUserRequest = operations['admin/suspend-user']['requestBody']['content']['application/json'];
@ -1276,6 +1294,12 @@ declare namespace entities {
AdminRolesUpdateDefaultPoliciesRequest,
AdminRolesUsersRequest,
AdminRolesUsersResponse,
AdminSsoCreateRequest,
AdminSsoCreateResponse,
AdminSsoDeleteRequest,
AdminSsoListRequest,
AdminSsoListResponse,
AdminSsoUpdateRequest,
AnnouncementsRequest,
AnnouncementsResponse,
AntennasCreateRequest,
@ -2457,7 +2481,7 @@ type ModerationLog = {
});
// @public (undocumented)
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createIndieAuthClient", "updateIndieAuthClient", "deleteIndieAuthClient", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner"];
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createIndieAuthClient", "updateIndieAuthClient", "deleteIndieAuthClient", "createSSOServiceProvider", "updateSSOServiceProvider", "deleteSSOServiceProvider", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner"];
// @public (undocumented)
type MuteCreateRequest = operations['mute/create']['requestBody']['content']['application/json'];
@ -2709,7 +2733,7 @@ type PagesUpdateRequest = operations['pages/update']['requestBody']['content']['
function parse(acct: string): Acct;
// @public (undocumented)
export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "read:admin:abuse-report-resolvers", "write:admin:abuse-report-resolvers", "write:admin:delete-account", "write:admin:delete-all-files-of-a-user", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-user", "read:admin:show-users", "write:admin:suspend-user", "write:admin:unset-user-avatar", "write:admin:unset-user-banner", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-note", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:indie-auth", "read:admin:indie-auth", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse"];
export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "read:admin:abuse-report-resolvers", "write:admin:abuse-report-resolvers", "write:admin:delete-account", "write:admin:delete-all-files-of-a-user", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-user", "read:admin:show-users", "write:admin:suspend-user", "write:admin:unset-user-avatar", "write:admin:unset-user-banner", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-note", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:indie-auth", "read:admin:indie-auth", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:sso", "read:admin:sso", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse"];
// @public (undocumented)
type PingResponse = operations['ping']['responses']['200']['content']['application/json'];

View file

@ -9,12 +9,12 @@
"devDependencies": {
"@misskey-dev/eslint-plugin": "^1.0.0",
"@readme/openapi-parser": "2.5.0",
"@types/node": "20.11.25",
"@typescript-eslint/eslint-plugin": "7.1.1",
"@typescript-eslint/parser": "7.1.1",
"@types/node": "20.11.27",
"@typescript-eslint/eslint-plugin": "7.2.0",
"@typescript-eslint/parser": "7.2.0",
"eslint": "8.57.0",
"openapi-types": "12.1.3",
"openapi-typescript": "6.7.4",
"openapi-typescript": "6.7.5",
"ts-case-convert": "2.0.7",
"tsx": "4.7.1",
"typescript": "5.4.2"

View file

@ -39,9 +39,9 @@
"@misskey-dev/eslint-plugin": "1.0.0",
"@swc/jest": "0.2.36",
"@types/jest": "29.5.12",
"@types/node": "20.11.25",
"@typescript-eslint/eslint-plugin": "7.1.1",
"@typescript-eslint/parser": "7.1.1",
"@types/node": "20.11.27",
"@typescript-eslint/eslint-plugin": "7.2.0",
"@typescript-eslint/parser": "7.2.0",
"eslint": "8.57.0",
"jest": "29.7.0",
"jest-fetch-mock": "3.0.3",

View file

@ -928,6 +928,50 @@ declare module '../api.js' {
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
request<E extends 'admin/sso/create', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
request<E extends 'admin/sso/delete', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:admin:sso*
*/
request<E extends 'admin/sso/list', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
request<E extends 'admin/sso/update', P extends Endpoints[E]['req']>(
endpoint: E,
params: P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>>;
/**
* No description provided.
*

View file

@ -111,6 +111,12 @@ import type {
AdminRolesUpdateDefaultPoliciesRequest,
AdminRolesUsersRequest,
AdminRolesUsersResponse,
AdminSsoCreateRequest,
AdminSsoCreateResponse,
AdminSsoDeleteRequest,
AdminSsoListRequest,
AdminSsoListResponse,
AdminSsoUpdateRequest,
AnnouncementsRequest,
AnnouncementsResponse,
AntennasCreateRequest,
@ -653,6 +659,10 @@ export type Endpoints = {
'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse };
'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse };
'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse };
'admin/sso/create': { req: AdminSsoCreateRequest; res: AdminSsoCreateResponse };
'admin/sso/delete': { req: AdminSsoDeleteRequest; res: EmptyResponse };
'admin/sso/list': { req: AdminSsoListRequest; res: AdminSsoListResponse };
'admin/sso/update': { req: AdminSsoUpdateRequest; res: EmptyResponse };
'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse };
'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse };
'antennas/delete': { req: AntennasDeleteRequest; res: EmptyResponse };

View file

@ -113,6 +113,12 @@ export type AdminRolesUnassignRequest = operations['admin/roles/unassign']['requ
export type AdminRolesUpdateDefaultPoliciesRequest = operations['admin/roles/update-default-policies']['requestBody']['content']['application/json'];
export type AdminRolesUsersRequest = operations['admin/roles/users']['requestBody']['content']['application/json'];
export type AdminRolesUsersResponse = operations['admin/roles/users']['responses']['200']['content']['application/json'];
export type AdminSsoCreateRequest = operations['admin/sso/create']['requestBody']['content']['application/json'];
export type AdminSsoCreateResponse = operations['admin/sso/create']['responses']['200']['content']['application/json'];
export type AdminSsoDeleteRequest = operations['admin/sso/delete']['requestBody']['content']['application/json'];
export type AdminSsoListRequest = operations['admin/sso/list']['requestBody']['content']['application/json'];
export type AdminSsoListResponse = operations['admin/sso/list']['responses']['200']['content']['application/json'];
export type AdminSsoUpdateRequest = operations['admin/sso/update']['requestBody']['content']['application/json'];
export type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json'];
export type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json'];
export type AntennasCreateRequest = operations['antennas/create']['requestBody']['content']['application/json'];

View file

@ -769,6 +769,42 @@ export type paths = {
*/
post: operations['admin/roles/users'];
};
'/admin/sso/create': {
/**
* admin/sso/create
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
post: operations['admin/sso/create'];
};
'/admin/sso/delete': {
/**
* admin/sso/delete
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
post: operations['admin/sso/delete'];
};
'/admin/sso/list': {
/**
* admin/sso/list
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:admin:sso*
*/
post: operations['admin/sso/list'];
};
'/admin/sso/update': {
/**
* admin/sso/update
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
post: operations['admin/sso/update'];
};
'/announcements': {
/**
* announcements
@ -10287,6 +10323,272 @@ export type operations = {
};
};
};
/**
* admin/sso/create
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
'admin/sso/create': {
requestBody: {
content: {
'application/json': {
name?: string | null;
/** @enum {string} */
type: 'saml' | 'jwt';
issuer: string;
/** @default [] */
audience?: string[];
acsUrl: string;
signatureAlgorithm: string;
cipherAlgorithm?: string | null;
/** @default false */
wantAuthnRequestsSigned?: boolean;
/** @default true */
wantAssertionsSigned?: boolean;
/** @default true */
useCertificate: boolean;
secret?: string | null;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': {
id: string;
/** Format: date-time */
createdAt: string;
name: string | null;
/** @enum {string} */
type: 'saml' | 'jwt';
issuer: string;
audience: string[];
acsUrl: string;
publicKey: string;
signatureAlgorithm: string;
cipherAlgorithm?: string | null;
wantAuthnRequestsSigned: boolean;
wantAssertionsSigned: boolean;
};
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* admin/sso/delete
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
'admin/sso/delete': {
requestBody: {
content: {
'application/json': {
id: string;
};
};
};
responses: {
/** @description OK (without any results) */
204: {
content: never;
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* admin/sso/list
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *read:admin:sso*
*/
'admin/sso/list': {
requestBody: {
content: {
'application/json': {
/** @default 10 */
limit?: number;
/** @default 0 */
offset?: number;
};
};
};
responses: {
/** @description OK (with results) */
200: {
content: {
'application/json': ({
id: string;
/** Format: date-time */
createdAt: string;
name: string | null;
/** @enum {string} */
type: 'saml' | 'jwt';
issuer: string;
audience: string[];
acsUrl: string;
publicKey: string;
signatureAlgorithm: string;
cipherAlgorithm?: string | null;
wantAuthnRequestsSigned: boolean;
wantAssertionsSigned: boolean;
})[];
};
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* admin/sso/update
* @description No description provided.
*
* **Credential required**: *Yes* / **Permission**: *write:admin:sso*
*/
'admin/sso/update': {
requestBody: {
content: {
'application/json': {
id: string;
name?: string;
issuer?: string;
audience?: string[];
acsUrl?: string;
signatureAlgorithm?: string;
cipherAlgorithm?: string;
wantAuthnRequestsSigned?: boolean;
wantAssertionsSigned?: boolean;
regenerateCertificate?: boolean;
secret?: string;
};
};
};
responses: {
/** @description OK (without any results) */
204: {
content: never;
};
/** @description Client error */
400: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Authentication error */
401: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Forbidden error */
403: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description I'm Ai */
418: {
content: {
'application/json': components['schemas']['Error'];
};
};
/** @description Internal server error */
500: {
content: {
'application/json': components['schemas']['Error'];
};
};
};
};
/**
* announcements
* @description No description provided.

View file

@ -89,6 +89,8 @@ export const permissions = [
'write:admin:promo',
'write:admin:drive',
'read:admin:drive',
'write:admin:sso',
'read:admin:sso',
'write:admin:ad',
'read:admin:ad',
'write:invite-codes',
@ -136,6 +138,9 @@ export const moderationLogTypes = [
'createIndieAuthClient',
'updateIndieAuthClient',
'deleteIndieAuthClient',
'createSSOServiceProvider',
'updateSSOServiceProvider',
'deleteSSOServiceProvider',
'createAvatarDecoration',
'updateAvatarDecoration',
'deleteAvatarDecoration',
@ -321,6 +326,19 @@ export type ModerationLogPayloads = {
clientId: string;
client: any;
};
createSSOServiceProvider: {
serviceId: string;
service: any;
};
updateSSOServiceProvider: {
serviceId: string;
before: any;
after: any;
};
deleteSSOServiceProvider: {
serviceId: string;
service: any;
};
createAvatarDecoration: {
avatarDecorationId: string;
avatarDecoration: any;