-
Behrisch, M. (Michael) authored
Replaces the custom made auth-backend (auth-gateway) with its token logic and complexity with established open-source FIPS 140-2 compliant authentification solution does not use auth-gateway anymore for authentification. close: #28
Behrisch, M. (Michael) authoredReplaces the custom made auth-backend (auth-gateway) with its token logic and complexity with established open-source FIPS 140-2 compliant authentification solution does not use auth-gateway anymore for authentification. close: #28
authorizationHook.tsx 4.82 KiB
import { useAppDispatch, useAuthorizationCache } from '../store';
import { authorized, unauthorized, updateAccessToken } from '../store/authSlice';
/**
* getNewAccessToken gets a new access token using the refresh-token cookie
* @returns an authResponse containing details
*/
async function getNewAccessToken(
domain: string,
accessToken: string
): Promise<authResponse> {
// If we have an access token already, append it to the url as a query param to keep sessionID the same
let url = `https://${domain}/auth/refresh`;
if (accessToken != '') {
url += '?access_token=' + accessToken;
}
try {
const response = await fetch(url, {
method: 'GET',
credentials: 'include',
});
if (!response.ok) {
// User is not authorized
const text = await response.text();
console.error('User UNAUTHORIZED', text);
return { success: false };
// throw Error(response.statusText);
}
const json = await response.json();
return {
success: true,
accessToken: json.accessToken,
userID: json.userID,
sessionID: json.sessionID,
};
} catch (error) {
console.error('Error authorizing user', error);
return { success: false };
}
}
type authResponse = {
success: boolean;
accessToken?: string;
userID?: string;
sessionID?: string;
};
export type useIsAuthorizedState = {
userID?: string;
sessionID?: string;
accessToken: string;
authorized?: boolean;
};
export function useAuthorization(domain: string) {
const dispatch = useAppDispatch();
const auth = useAuthorizationCache();
/**
* refreshTokens refreshes tokens
*/
async function refreshTokens() {
console.log('refreshing tokens');
// Get a new access + refresh token pair
const authResponse = await getNewAccessToken(domain, auth.accessToken);
if (authResponse.success) {
// Set the new access token
dispatch(updateAccessToken(authResponse.accessToken ?? ''));
if (auth.accessToken !== '') {
// Initialize the new refresh token
initializeRefreshToken();
}
}
}
// /**
// * initializeRefreshToken attempts to initialize a refresh token
// */
// async function refreshRefreshToken() {
// fetch(
// 'https://${domain}/auth/refresh?access_token=' +
// state.accessToken,
// {
// method: 'GET',
// credentials: 'include',
// }
// )
// .then((response) => {
// if (!response.ok) {
// throw Error(response.statusText);
// }
// })
// .catch((error) => {
// console.error(error);
// });
// }
/**
* initializeRefreshToken attempts to initialize a refresh token
*/
async function initializeRefreshToken() {
fetch(`https://${domain}/auth/refresh`, {
method: 'POST',
credentials: 'include',
})
.then((response) => {
if (!response.ok) {
console.error(response.statusText);
// throw Error(response.statusText);
}
})
.catch((error) => {
console.error(error);
});
}
// MARK: Setters
/**
* SetAccessToken sets the current access token (should only be called by the sign-in component)
* @param accessToken
*/
async function SetAccessToken(accessToken: string) {
dispatch(updateAccessToken(accessToken));
console.log('set access token', auth.accessToken);
const result = await AuthorizeFromCache();
if (result) {
// Activate the refresh token TODO
initializeRefreshToken();
// Start the automatic refreshing every 10 minutes
setInterval(() => {
refreshTokens();
}, 10 * 60 * 1000);
} else {
console.error(
'Failed Logging in due to refresh token initialization',
result
);
// throw Error('Failed Logging in');
}
}
/**
* Authorize attempts to authorize using a refresh-token set as a cookie. If the user has been inactive for more than 7 days this cookie will be gone.
* @returns true is authorization was successful, else returns false
*/
async function AuthorizeFromCache(): Promise<boolean> {
// Attempt to log in with a refresh-token
const authResponse = await getNewAccessToken(domain, auth.accessToken);
// If the request was a success, we have an accessToken, userID and sessionID
if (authResponse.success) {
console.log('SUCCESS authorize');
console.log(auth);
// Store them
await dispatch(
authorized({
userID: authResponse.userID ?? '',
sessionID: authResponse.sessionID ?? '',
accessToken: authResponse.accessToken ?? '',
authorized: true,
})
);
} else {
await dispatch(
unauthorized()
);
}
return authResponse.success;
}
return {
AuthorizeFromCache,
SetAccessToken,
auth,
};
}