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.
96 lines
2.9 KiB
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
|
|
}
|
|
}
|