token.ts (1978B)
1 import { ClientRepository } from "#core/application/oauth2/client_repository.ts"; 2 import { OAuth2FlowRepository } from "#core/application/oauth2/flow_repository.ts"; 3 import { EntityNotFound } from "../repository_error.ts"; 4 import { InvalidOAuth2Flow } from "#core/domain/oauth2flow.ts"; 5 import { InvalidToken, Token } from "#core/domain/token.ts"; 6 import { InvalidUUID, UUID } from "#core/domain/uuid.ts"; 7 8 export type OAuth2FlowTokenRequest = { 9 clientId: string; 10 clientSecret: string; 11 code: string; 12 }; 13 14 export type OAuth2FlowTokenResponse = { 15 status: "issued" | "invalid"; 16 accessToken: string | null; 17 scope: string | null; 18 expire: number; 19 state: string | null; 20 }; 21 22 export class OAuth2FlowTokenUseCase { 23 constructor( 24 private readonly clientRepo: ClientRepository, 25 private readonly flowRepo: OAuth2FlowRepository, 26 ) {} 27 28 async execute( 29 request: OAuth2FlowTokenRequest, 30 ): Promise<OAuth2FlowTokenResponse> { 31 try { 32 const clientId = new UUID(request.clientId); 33 const code = new Token(request.code); 34 const client = await this.clientRepo.find(clientId); 35 const flow = await this.flowRepo.findByToken(code); 36 try { 37 const accessToken = client.accessToken( 38 flow, 39 request.clientSecret, 40 request.code, 41 ); 42 return { 43 status: "issued", 44 accessToken: accessToken.toString(), 45 scope: flow.scope.toString(), 46 expire: flow.expire, 47 state: flow.state, 48 }; 49 } finally { 50 await this.flowRepo.store(flow); 51 } 52 } catch (error) { 53 if ( 54 error instanceof InvalidUUID || 55 error instanceof InvalidToken || 56 error instanceof EntityNotFound || 57 error instanceof InvalidOAuth2Flow 58 ) { 59 return { 60 status: "invalid", 61 accessToken: null, 62 scope: null, 63 expire: 0, 64 state: null, 65 }; 66 } 67 throw error; 68 } 69 } 70 }