sso-core/src/lib/server/oauth2/response.ts

137 lines
3.1 KiB
TypeScript

import { redirect } from '@sveltejs/kit';
import { OAuth2Error } from './error';
interface ErrorResponseData {
[x: string]: string | undefined;
error: string;
error_description: string;
state?: string;
}
export interface OAuth2TokenResponse {
id_token?: string;
access_token?: string;
refresh_token?: string;
expires_in?: number;
token_type?: string;
state?: string;
active?: boolean;
scope?: string;
client_id?: string;
exp?: number;
}
export class OAuth2Response {
static createResponse(code: number, data: unknown) {
const isJson = typeof data === 'object';
const body = isJson ? JSON.stringify(data) : (data as string);
return new Response(body, {
status: code,
headers: {
'Content-Type': isJson ? 'application/json' : 'application/octet-stream'
}
});
}
static createErrorResponse(err: OAuth2Error) {
return OAuth2Response.createResponse(err.status, {
error: err.code,
error_description: err.message
});
}
static redirect(redirectUri: string) {
return redirect(302, redirectUri);
}
static error(url: URL, err: OAuth2Error, redirectUri?: string) {
if (!(err instanceof OAuth2Error)) {
throw err;
}
if (redirectUri) {
const obj: ErrorResponseData = {
error: err.code,
error_description: err.message
};
if (url.searchParams.has('state')) {
obj.state = url.searchParams.get('state') as string;
}
redirectUri += '?' + new URLSearchParams(obj as Record<string, string>).toString();
return redirect(302, redirectUri);
}
return OAuth2Response.createErrorResponse(err);
}
static errorPlain(url: URL, err: OAuth2Error, redirectUri?: string) {
if (!(err instanceof OAuth2Error)) {
throw err;
}
if (redirectUri) {
const obj: ErrorResponseData = {
error: err.code,
error_description: err.message
};
if (url.searchParams.has('state')) {
obj.state = url.searchParams.get('state') as string;
}
redirectUri += '?' + new URLSearchParams(obj as Record<string, string>).toString();
return redirect(302, redirectUri);
}
return {
error: err.code,
error_description: err.message
};
}
static response(
url: URL,
obj: OAuth2TokenResponse,
redirectUri?: string,
fragment: boolean = false
) {
if (redirectUri) {
redirectUri += fragment ? '#' : redirectUri.indexOf('?') === -1 ? '?' : '&';
if (url.searchParams.has('state')) {
obj.state = url.searchParams.get('state') as string;
}
redirectUri += new URLSearchParams(obj as Record<string, string>).toString();
return redirect(302, redirectUri);
}
return OAuth2Response.createResponse(200, obj);
}
static responsePlain(
url: URL,
obj: OAuth2TokenResponse,
redirectUri?: string,
fragment: boolean = false
) {
if (redirectUri) {
const searchJoinChar = redirectUri.includes('?') ? '&' : '?';
redirectUri += fragment ? '#' : searchJoinChar;
if (url.searchParams.has('state')) {
obj.state = url.searchParams.get('state') as string;
}
redirectUri += new URLSearchParams(obj as Record<string, string>).toString();
return redirect(302, redirectUri);
}
return obj;
}
}