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/server/types.ts

175 lines
4.8 KiB

import {Awaitable, hasOwnProperty, Maybe, TypeTag} from '../../util'
import {Authenticatable, AuthenticatableIdentifier} from '../types'
export enum OAuth2FlowType {
code = 'code',
}
// export const oauth2FlowTypes: OAuth2FlowType[] = Object.entries(OAuth2FlowType).map(([_, value]) => value)
export function isOAuth2FlowType(what: unknown): what is OAuth2FlowType {
return [OAuth2FlowType.code].includes(what as any)
}
export interface OAuth2Client {
id: string
display: string
secret: string
allowedFlows: OAuth2FlowType[]
allowedScopeIds: string[]
allowedRedirectUris: string[]
}
export function isOAuth2Client(what: unknown): what is OAuth2Client {
if ( typeof what !== 'object' || what === null ) {
return false
}
if (
!hasOwnProperty(what, 'id')
|| !hasOwnProperty(what, 'display')
|| !hasOwnProperty(what, 'secret')
|| !hasOwnProperty(what, 'allowedFlows')
|| !hasOwnProperty(what, 'allowedScopeIds')
|| !hasOwnProperty(what, 'allowedRedirectUris')
) {
return false
}
if ( typeof what.id !== 'string' || typeof what.display !== 'string' || typeof what.secret !== 'string' ) {
return false
}
if ( !Array.isArray(what.allowedScopeIds) || !what.allowedScopeIds.every(x => typeof x === 'string') ) {
return false
}
if ( !Array.isArray(what.allowedRedirectUris) || !what.allowedRedirectUris.every(x => typeof x === 'string') ) {
return false
}
return !(!Array.isArray(what.allowedFlows) || !what.allowedFlows.every(x => isOAuth2FlowType(x)))
}
export abstract class ClientRepository {
abstract find(id: string): Awaitable<Maybe<OAuth2Client>>
}
export interface OAuth2Scope {
id: string
name: string
description?: string
}
export function isOAuth2Scope(what: unknown): what is OAuth2Scope {
if ( typeof what !== 'object' || what === null ) {
return false
}
if ( !hasOwnProperty(what, 'id') || !hasOwnProperty(what, 'name') ) {
return false
}
if ( typeof what.id !== 'string' || typeof what.name !== 'string' ) {
return false
}
return !hasOwnProperty(what, 'description') || typeof what.description === 'string'
}
export abstract class ScopeRepository {
abstract find(id: string): Awaitable<Maybe<OAuth2Scope>>
abstract findByName(name: string): Awaitable<Maybe<OAuth2Scope>>
}
export interface OAuth2Token {
id: string
userId: AuthenticatableIdentifier
clientId: string
issued: Date
expires: Date
scope?: string
}
export type OAuth2TokenString = TypeTag<'@extollo/lib.OAuth2TokenString'> & string
export function oauth2TokenString(s: string): OAuth2TokenString {
return s as OAuth2TokenString
}
export function isOAuth2Token(what: unknown): what is OAuth2Token {
if ( typeof what !== 'object' || what === null ) {
return false
}
if (
!hasOwnProperty(what, 'id')
|| !hasOwnProperty(what, 'userId')
|| !hasOwnProperty(what, 'clientId')
|| !hasOwnProperty(what, 'issued')
|| !hasOwnProperty(what, 'expires')
) {
return false
}
if (
typeof what.id !== 'string'
|| !(typeof what.userId === 'string' || typeof what.userId === 'number')
|| typeof what.clientId !== 'string'
|| !(what.issued instanceof Date)
|| !(what.expires instanceof Date)
) {
return false
}
return !hasOwnProperty(what, 'scope') || typeof what.scope === 'string'
}
export abstract class TokenRepository {
abstract find(id: string): Awaitable<Maybe<OAuth2Token>>
abstract issue(user: Authenticatable, client: OAuth2Client, scope?: string): Awaitable<OAuth2Token>
abstract decode(token: OAuth2TokenString): Awaitable<Maybe<OAuth2Token>>
abstract encode(token: OAuth2Token): Awaitable<OAuth2TokenString>
}
export interface OAuth2RedemptionCode {
clientId: string
userId: AuthenticatableIdentifier
code: string
scope?: string
}
export function isOAuth2RedemptionCode(what: unknown): what is OAuth2RedemptionCode {
if ( typeof what !== 'object' || what === null ) {
return false
}
if (
!hasOwnProperty(what, 'clientId')
|| !hasOwnProperty(what, 'userId')
|| !hasOwnProperty(what, 'code')
) {
return false
}
if (
typeof what.clientId !== 'string'
|| !(typeof what.userId === 'number' || typeof what.userId === 'string')
|| typeof what.code !== 'string'
) {
return false
}
return !hasOwnProperty(what, 'scope') || typeof what.scope === 'string'
}
export abstract class RedemptionCodeRepository {
abstract find(code: string): Awaitable<Maybe<OAuth2RedemptionCode>>
abstract issue(user: Authenticatable, client: OAuth2Client, scope?: string): Awaitable<OAuth2RedemptionCode>
}