diff --git a/src/mfa.ts b/src/mfa.ts new file mode 100644 index 0000000..7c23f62 --- /dev/null +++ b/src/mfa.ts @@ -0,0 +1,117 @@ +// Copyright 2021 The Casdoor Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { AxiosResponse } from 'axios' +import * as FormData from 'form-data' +import { Config } from './config' +import Request from './request' + +export enum MfaType { + EMAIL = 'email', + SMS = 'sms', + APP = 'app', +} + +export interface MfaData { + owner: string + mfaType: MfaType + name: string +} + +export interface CasdoorMfaProps { + enabled?: boolean + isPreferred?: boolean + mfaType?: string + secret?: string + countryCode?: string + url?: string + recoveryCodes?: string +} + +export class MfaSDK { + private config: Config + private readonly request: Request + + constructor(config: Config, request: Request) { + this.config = config + this.request = request + } + + private prepareMfaPayload(data: MfaData) { + const formData = new FormData() + formData.append('owner', data.owner) + formData.append('mfaType', data.mfaType) + formData.append('name', data.name) + return formData + } + + public async initiate(data: MfaData) { + if (!this.request) { + throw new Error('request init failed') + } + const payload = this.prepareMfaPayload(data) + console.log(payload) + return (await this.request.post('mfa/setup/initiate', payload, { + headers: payload.getHeaders(), + })) as unknown as Promise> + } + + public async verify(data: MfaData, passcode: string) { + if (!this.request) { + throw new Error('request init failed') + } + + const payload = this.prepareMfaPayload(data) + payload.append('passcode', passcode) + return (await this.request.post('mfa/setup/verify', payload, { + headers: payload.getHeaders(), + })) as unknown as Promise> + } + + public async enable(data: MfaData) { + if (!this.request) { + throw new Error('request init failed') + } + + const payload = this.prepareMfaPayload(data) + console.log(payload) + return (await this.request.post('mfa/setup/enable', payload, { + headers: payload.getHeaders(), + })) as unknown as Promise> + } + + public async setPreferred(data: MfaData) { + if (!this.request) { + throw new Error('request init failed') + } + + const payload = this.prepareMfaPayload(data) + return (await this.request.post('set-preferred-mfa', payload, { + headers: payload.getHeaders(), + })) as unknown as Promise> + } + + public async delete(owner: string, name: string) { + if (!this.request) { + throw new Error('request init failed') + } + + const formData = new FormData() + formData.append('owner', owner) + formData.append('name', name) + return (await this.request.post('delete-mfa', formData, { + headers: formData.getHeaders(), + })) as unknown as Promise> + } +} diff --git a/src/sdk.ts b/src/sdk.ts index 764f51a..6007eac 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -37,6 +37,7 @@ import { Webhook, WebhookSDK } from './webhook' import { Product, ProductSDK } from './product' import { Email, EmailSDK } from './email' import { Sms, SmsSDK } from './sms' +import { MfaData, MfaSDK } from './mfa' export class SDK { private readonly config: Config @@ -64,6 +65,7 @@ export class SDK { private productSDK: ProductSDK private emailSDK: EmailSDK private smsSDK: SmsSDK + private mfaSDK: MfaSDK constructor(config: Config) { this.config = config @@ -101,6 +103,7 @@ export class SDK { this.productSDK = new ProductSDK(this.config, this.request) this.emailSDK = new EmailSDK(this.config, this.request) this.smsSDK = new SmsSDK(this.config, this.request) + this.mfaSDK = new MfaSDK(this.config, this.request) } public async getAuthToken(code: string) { @@ -568,4 +571,24 @@ export class SDK { public async setPassword(data: SetPassword) { return await this.userSDK.setPassword(data) } + + public async initiateMfa(data: MfaData) { + return await this.mfaSDK.initiate(data) + } + + public async verifyMfa(data: MfaData, passcode: string) { + return await this.mfaSDK.verify(data, passcode) + } + + public async enableMfa(data: MfaData) { + return await this.mfaSDK.enable(data) + } + + public async setPreferredMfa(data: MfaData) { + return await this.mfaSDK.setPreferred(data) + } + + public async deleteMfa(owner: string, name: string) { + return await this.mfaSDK.delete(owner, name) + } } diff --git a/src/user.ts b/src/user.ts index 6163c9a..a41e598 100644 --- a/src/user.ts +++ b/src/user.ts @@ -17,6 +17,7 @@ import * as jwt from 'jsonwebtoken' import * as FormData from 'form-data' import { Config } from './config' import Request from './request' +import { CasdoorMfaProps } from './mfa' export interface User { owner: string @@ -95,6 +96,14 @@ export interface User { ldap?: string properties?: Record + + //mfa + preferredMfaType?: string + recoveryCodes?: string[] + totpSecret?: string + mfaPhoneEnabled?: boolean + mfaEmailEnabled?: boolean + multiFactorAuths?: CasdoorMfaProps[] } export interface SetPassword {