bam-ticketing-sdk
Version:
SDK for B.A.M Ticketing API
208 lines (190 loc) • 5.19 kB
text/typescript
import { AxiosInstance, AxiosResponse } from 'axios'
import {
Jwt,
Nonce,
UserPassword,
RefreshToken,
RefreshableJwt,
SignedWalletChallenge,
WalletChallengeRequest,
ServiceAccessData,
ThirdPartyAuth,
ThirdPartyAuthResponse,
ImpersonateRequest,
} from './types'
import { KeyPair } from '..'
import { sign, extractEnrollment } from '../utils/certificate'
/**
* Service class for account API calls.
*/
export class AuthService {
constructor(readonly client: AxiosInstance, readonly version: string) {}
/**
* Returns a JWT and its refresh token.
*
* @param refreshToken refresh token object
* @returns JWT and refresh token
* @throws `NotFoundError`, `UnauthorizedError`
*/
async refreshToken(refreshToken: RefreshToken): Promise<RefreshableJwt> {
const res = await this.client.post(
`account/${this.version}/auth/refresh`,
refreshToken
)
return res.data.data
}
/**
* Returns a JWT and its refresh token.
* Enables accessing secured BAM endpoints.
* Username can also be the user's email.
*
* @param credentials username/email and password
* @returns JWT and refresh token
* @throws `NotFoundError`, `UnauthorizedError`
*/
async login(credentials: UserPassword): Promise<RefreshableJwt> {
const res = await this.client.post(
`account/${this.version}/auth/login`,
credentials
)
return res.data.data
}
/**
* Returns a JWT for a newly-created anonymous user.
* This user has no permissions.
*
* @returns JWT for an generated user
*/
async guestLogin(): Promise<Jwt> {
// Empty body because there has to be one for application/json
const res = await this.client.post(
`account/${this.version}/guest/login`,
{}
)
return res.data.data
}
/**
* Returns a nonce which has to be signed with the user's wallet to obtain a JWT.
* Enables accessing secured BAM endpoints.
* After signing you need to call walletLogin.
*
* @param req enroll
* @returns nonce to sign
* @throws `BadRequestError`
*/
async getWalletChallenge(req: WalletChallengeRequest): Promise<Nonce> {
const res = await this.client.post(
`account/${this.version}/auth/challenge`,
req
)
return res.data.data
}
/**
* Returns a JWT and its refresh token.
* Enables accessing secured BAM endpoints.
* Requires the device ID header to be set.
*
* @param signedChallenge contains a nonce signed by the users wallet
* @returns JWT and refresh token
* @throws `NotFoundError`, `BadRequestError`
*/
async walletLogin(
signedChallenge: SignedWalletChallenge
): Promise<RefreshableJwt> {
const res = await this.client.post(
`account/${this.version}/auth/wallet`,
signedChallenge
)
return res.data.data
}
/**
* Returns a JWT and its refresh token.
* Enables accessing secured BAM endpoints.
*
* @param keyPair contains a nonce signed by the users wallet
* @returns JWT and refresh token
* @throws `NotFoundError`, `BadRequestError`
*/
async loginWithCertificate(
wallet: KeyPair,
organizerId?: string
): Promise<RefreshableJwt> {
// Get a challenge for the user
const challengeRequest = {
clientNonce: Date.now().toString(),
enrollmentId: extractEnrollment(wallet.certificate),
}
const challenge = await this.getWalletChallenge(challengeRequest)
// Sign the challenge
const signedChallenge = {
clientNonce: challengeRequest.clientNonce,
nonce: challenge.nonce,
signedNonce: sign(challenge.nonce, wallet.privateKey),
organizerId,
}
// Login
return this.walletLogin(signedChallenge)
}
/**
* Returns a JWT for a service.
* Enables accessing secured BAM endpoints.
*
* @param credentials service name, org and password
* @returns JWT
* @throws `NotFoundError`, `UnauthorizedError`
*/
async serviceLogin(credentials: ServiceAccessData): Promise<Jwt> {
const res = await this.client.post(
`account/${this.version}/auth/service`,
credentials
)
return res.data.data
}
/**
* Returns a JWT for a service.
* Enables external login via OAuth.
* Token is provided by the third party.
*
* @param req User data for login
* @returns JWT and refresh token
*/
async externalLogin(req: ThirdPartyAuth): Promise<ThirdPartyAuthResponse> {
const res = await this.client.post(
`account/${this.version}/auth/external`,
req
)
return res.data.data
}
/**
* Returns an impersonated JWT, if you have the permissions to get it.
* If you specify an organizerId, the requested JWT will contain the permissions
* that the userId user has for that organizerId
*
* @param req Impersonated user data
* @param adminCredentials if provided, this token will be used for the request
* @returns Impersonation JWT
*/
async impersonate(
req: ImpersonateRequest,
adminCredentials?: Jwt
): Promise<Jwt> {
let res: AxiosResponse
if (adminCredentials) {
res = await this.client.post(
`account/${this.version}/auth/impersonate`,
req,
{
headers: {
Authorization: `Bearer ${adminCredentials.token}`,
},
}
)
} else {
res = await this.client.post(
`account/${this.version}/auth/impersonate`,
req
)
}
return res.data.data
}
}