You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/auth/external/oauth2/OAuth2LoginController.ts

96 lines
2.9 KiB

import {Controller} from '../../../http/Controller'
import {Inject, Injectable} from '../../../di'
import {Config} from '../../../service/Config'
import {Request} from '../../../http/lifecycle/Request'
import {ResponseObject, Route} from '../../../http/routing/Route'
import {ErrorWithContext} from '../../../util'
import {OAuth2Repository} from './OAuth2Repository'
import {json} from '../../../http/response/JSONResponseFactory'
export interface OAuth2LoginConfig {
name: string,
clientId: string,
clientSecret: string,
redirectUrl: string,
authorizationCodeField: string,
tokenEndpoint: string,
tokenEndpointMapping?: {
clientId?: string,
clientSecret?: string,
grantType?: string,
codeKey?: string,
},
tokenEndpointResponseMapping?: {
token?: string,
expiresIn?: string,
expiresAt?: string,
},
userEndpoint: string,
userEndpointResponseMapping?: {
identifier?: string,
display?: string,
},
}
export function isOAuth2LoginConfig(what: unknown): what is OAuth2LoginConfig {
return (
Boolean(what)
&& typeof (what as any).name === 'string'
&& typeof (what as any).clientId === 'string'
&& typeof (what as any).clientSecret === 'string'
&& typeof (what as any).redirectUrl === 'string'
&& typeof (what as any).authorizationCodeField === 'string'
&& typeof (what as any).tokenEndpoint === 'string'
&& typeof (what as any).userEndpoint === 'string'
)
}
@Injectable()
export class OAuth2LoginController extends Controller {
public static routes(configName: string): void {
Route.group(`/auth/${configName}`, () => {
Route.get('login', (request: Request) => {
const controller = <OAuth2LoginController> request.make(OAuth2LoginController, configName)
return controller.getLogin()
}).pre('@auth:guest')
}).pre('@auth:web')
}
@Inject()
protected readonly config!: Config
constructor(
protected readonly request: Request,
protected readonly configName: string,
) {
super(request)
}
public async getLogin(): Promise<ResponseObject> {
const repo = this.getRepository()
if ( repo.shouldRedirect() ) {
return repo.redirect()
}
// We were redirected from the auth source
const user = await repo.redeem()
return json(user)
}
protected getRepository(): OAuth2Repository {
return this.request.make(OAuth2Repository, this.getConfig())
}
protected getConfig(): OAuth2LoginConfig {
const config = this.config.get(`auth.sources.${this.configName}`)
if ( !isOAuth2LoginConfig(config) ) {
throw new ErrorWithContext('Invalid OAuth2 source config.', {
configName: this.configName,
config,
})
}
return config
}
}