mirror of
https://github.com/janishutz/oidc-login-sdk.git
synced 2026-10-08 17:36:20 +02:00
feat: improve authentication checks and request lib
This commit is contained in:
1 parent
374e1dfc9e
commit
e3d1bd7a62
3 files changed
+66
-15
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@janishutz/oidc-login-sdk-browser",
|
"name": "@janishutz/oidc-login-sdk-browser",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"description": "SDK to communicate with and log into a backend running express-openid-connect",
|
"description": "SDK to communicate with and log into a backend running express-openid-connect",
|
||||||
"homepage": "https://github.com/janishutz/oidc-login-sdk#readme",
|
"homepage": "https://github.com/janishutz/oidc-login-sdk#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|||||||
+17
-3
@@ -3,12 +3,20 @@ import request, {
|
|||||||
} from './request.js';
|
} from './request.js';
|
||||||
import config from './config.js';
|
import config from './config.js';
|
||||||
|
|
||||||
export const login = ( returnTo?: string ) => {
|
/**
|
||||||
|
* Start the login flow. Please note that upon calling this, the page will be reloaded after completion of the login flow
|
||||||
|
* @param returnTo - The location to return to after login
|
||||||
|
*/
|
||||||
|
export const login = ( returnTo?: URL ) => {
|
||||||
sessionStorage.setItem( 'redirect', location.pathname );
|
sessionStorage.setItem( 'redirect', location.pathname );
|
||||||
location.href = ( config.get().loginEndpoint ?? '/auth/v2/login' ) + ( returnTo ? returnTo : '' );
|
location.href = ( config.get().loginEndpoint ?? '/auth/v2/login' ) + ( returnTo ? returnTo.toString() : '' );
|
||||||
};
|
};
|
||||||
|
|
||||||
export const check = async () => {
|
/**
|
||||||
|
* Check if a user is authenticated. This can also be done implicitly using a call to a protected endpoint
|
||||||
|
* @returns A promise resolving to a boolean indicating authentication status
|
||||||
|
*/
|
||||||
|
export const check = async (): Promise<boolean> => {
|
||||||
let status: boolean;
|
let status: boolean;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -31,6 +39,11 @@ export const check = async () => {
|
|||||||
return status;
|
return status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this, if you did not set the login returnTo path, or if in any other case you need to redirect the user after login,
|
||||||
|
* such as after a navigation guard executing prior to state update
|
||||||
|
* @returns The location to redirect to
|
||||||
|
*/
|
||||||
export const getRedirect = (): string | null => {
|
export const getRedirect = (): string | null => {
|
||||||
const item = sessionStorage.getItem( 'redirect' );
|
const item = sessionStorage.getItem( 'redirect' );
|
||||||
|
|
||||||
@@ -39,6 +52,7 @@ export const getRedirect = (): string | null => {
|
|||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Logs the user out */
|
||||||
export const logout = async () => {
|
export const logout = async () => {
|
||||||
location.href = config.get().logoutEndpoint ?? '/auth/v2/logout';
|
location.href = config.get().logoutEndpoint ?? '/auth/v2/logout';
|
||||||
};
|
};
|
||||||
+48
-11
@@ -11,12 +11,26 @@ export class AuthError extends Error {}
|
|||||||
export class UnownedError extends Error {}
|
export class UnownedError extends Error {}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an HTTP GET request
|
||||||
|
* @param url - The URL (just the path relative to website root) to fetch
|
||||||
|
* @param authErrorResolution - The mean of authentication error resolution
|
||||||
|
* @returns The reponse
|
||||||
|
*/
|
||||||
const get = async ( url: string, authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
const get = async ( url: string, authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
||||||
return await wrapper( url, {
|
return await wrapper( url, {
|
||||||
'credentials': 'include'
|
'credentials': 'include'
|
||||||
}, authErrorResolution );
|
}, authErrorResolution );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an HTTP POST request
|
||||||
|
* @param url - The URL (just the path relative to website root) to fetch
|
||||||
|
* @param payload - The request body to send as a string
|
||||||
|
* @param mime - The MIME type of the payload
|
||||||
|
* @param authErrorResolution - The mean of authentication error resolution
|
||||||
|
* @returns The response
|
||||||
|
*/
|
||||||
const post = async ( url: string, payload: string, mime: string = 'application/json', authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
const post = async ( url: string, payload: string, mime: string = 'application/json', authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
||||||
return await wrapper( url, {
|
return await wrapper( url, {
|
||||||
'credentials': 'include',
|
'credentials': 'include',
|
||||||
@@ -28,6 +42,19 @@ const post = async ( url: string, payload: string, mime: string = 'application/j
|
|||||||
}, authErrorResolution );
|
}, authErrorResolution );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an HTTP DELETE request
|
||||||
|
* @param url - The URL (just the path relative to website root) to fetch
|
||||||
|
* @param authErrorResolution - The mean of authentication error resolution
|
||||||
|
* @returns The response
|
||||||
|
*/
|
||||||
|
const deleteRequest = async ( url: string, authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
||||||
|
return await wrapper( url, {
|
||||||
|
'credentials': 'include',
|
||||||
|
'method': 'delete'
|
||||||
|
}, authErrorResolution );
|
||||||
|
};
|
||||||
|
|
||||||
const wrapper = async ( url: string, opts: RequestInit, authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
const wrapper = async ( url: string, opts: RequestInit, authErrorResolution?: AuthErrorResolution ): Promise<Response> => {
|
||||||
const res = await fetch( config.get().backendURL + url, {
|
const res = await fetch( config.get().backendURL + url, {
|
||||||
'redirect': 'manual',
|
'redirect': 'manual',
|
||||||
@@ -35,23 +62,33 @@ const wrapper = async ( url: string, opts: RequestInit, authErrorResolution?: Au
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
if ( res.type === 'opaqueredirect' ) {
|
if ( res.type === 'opaqueredirect' ) {
|
||||||
if ( config.get().authErrorEvent ) {
|
handleUnauth( authErrorResolution );
|
||||||
document.dispatchEvent( new CustomEvent( 'autherror' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ( authErrorResolution && authErrorResolution === 'resolve' ) || ( !authErrorResolution && config.get().defaultAuthErrorResolution === 'resolve' ) ) {
|
|
||||||
login();
|
|
||||||
} else {
|
|
||||||
throw new AuthError( 'ERR_USER_UNAUTHORIZED' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return res;
|
if ( res.ok )
|
||||||
|
return res;
|
||||||
|
else if ( res.status === 401 || res.status === 403 )
|
||||||
|
throw new AuthError( 'ERR_USER_UNAUTHORIZED' );
|
||||||
|
else
|
||||||
|
throw new Error( 'ERR_' + res.status );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUnauth = ( authErrorResolution: AuthErrorResolution ) => {
|
||||||
|
if ( config.get().authErrorEvent ) {
|
||||||
|
document.dispatchEvent( new CustomEvent( 'autherror' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( authErrorResolution && authErrorResolution === 'resolve' ) || ( !authErrorResolution && config.get().defaultAuthErrorResolution === 'resolve' ) ) {
|
||||||
|
login();
|
||||||
|
} else {
|
||||||
|
throw new AuthError( 'ERR_USER_UNAUTHORIZED' );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
get,
|
get,
|
||||||
post
|
post,
|
||||||
|
'delete': deleteRequest
|
||||||
};
|
};
|
||||||
Reference in new issue
Block a user