architecture-it/react-auth¶
Descripción¶
Librería React-Auth que permite autenticarte con diferentes proveedores de identidad siempre que utilicen los protocolos de autorización y autenticación OAuth2 y OIDC. Se tomó como base la librería react-oauth2-code-pkce y se adaptó para que trabaje con client-secret en los casos que lo requiera (es configurable). Además se incorporó las funcionalidades necesarias para interpretar todos los flujos de Azure AD B2C y el manejo de las custom policies (también configurables).
Features¶
- Permite realizar una llamada previa y/o posterior al inicio de sesión.
- Actualiza silenciosamente los tokens de acceso de corta duración en segundo plano
- Decodifica JWT
- Permite adaptarse a idps que no cumplan con el standar por medio de los extraParameters.
- Exporta funciones utiles como: isB2C : Si el proveedor es Azure B2C DecodeJWT : Recibe un token y retorna el decode.
Configuración¶
Parámetros¶
El AuthProvider recibe un objeto que trabaja con estos parametros:
export type TAuthConfig = {
clientId: string;
authorizationEndpoint: string;
redirectUri: string;
scope?: string;
state?: string;
logoutRedirect?: string;
tokenEndpoint?: string; // don´t use for AD B2C
logoutEndpoint?: string; // don´t use for AD B2C
tokenRevokeEndpoint?: string; //don´t use for AD B2C
preLogin?: () => void; //action to execute pre login
postLogin?: () => void;//action to execute post login
decodeToken?: boolean; //default true
autoLogin?: boolean; //redirects to login when launching the app. Default true
clearURL?: boolean;
extraAuthParams?: { [key: string]: string | boolean | number };
extraAuthParameters?: { [key: string]: string | boolean | number };
extraTokenParameters?: { [key: string]: string | boolean | number };
extraLogoutParameters?: { [key: string]: string | boolean | number };
tokenExpiresIn?: number;
refreshTokenExpiresIn?: number;
storage?: "session" | "local";
customPolicies?: ICustomPolicies; //use only for ADB2C
clientSecret?: string;
};
Importante
Para la configuracion con azure B2C el unico endpoint que se debe configurar es el authorizationEndpoint con la url del TenantDomain. Tambien es importante enviar las customPolicie ya que no toma ninguna por default. Las properties extraParameters permiten adaptar aquellos idp que no forman parte del standar.
Enviroment¶
En el template se adaptó un modelo que toma en cuenta las variables de entorno utilizando la librería interna para las variables de entorno architecture-it/react-env para realizar la comunicacion con el identity provider que se desee implementar.
Por lo que se deben completar las variables de entorno de acuerdo al provider que se va a utilizar, a continuación un ejemplo de la configuración con el Provider standar dentro de la compañia:
REACT_APP_CLIENT_ID=58fb34da-0a3e-45f6-aa35-f806a684433a
REACT_APP_AUTH_DOMAIN=https://andreanib2cdev.b2clogin.com/andreanib2cdev.onmicrosoft.com
REACT_APP_REDIRECTURI=http://localhost:3000
REACT_APP_B2C_SIGNUPSIGNIN=B2C_1A_SIGNUP_SIGNINAAD
REACT_APP_B2C_FORGOTPASSWORD=B2C_1A_PASSWORDRESET
REACT_APP_B2C_EDITPROFILE=B2C_1A_PROFILEEDIT
REACT_APP_CLIENT_ID=745628305089-gclpkcac8vnrk5clo1e32g9tnh5l6tvv.apps.googleusercontent.com
REACT_APP_AUTH_DOMAIN=https://accounts.google.com/o/oauth2/v2/auth
REACT_APP_TOKEN_ENDPOINT=https://oauth2.googleapis.com/token
REACT_APP_TOKEN_REVOKE=https://oauth2.googleapis.com/revoke
REACT_APP_REDIRECTURI=http://localhost:3000
REACT_APP_CLIENT_SECRET=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
REACT_APP_SCOPE='email openid profile'
REACT_APP_CLIENT_ID=745628305089-gclpkcac8vnrk5clo1e32g9tnh5l6tvv.apps.googleusercontent.com
REACT_APP_AUTH_DOMAIN=https://accounts.google.com/o/oauth2/v2/auth
REACT_APP_TOKEN_ENDPOINT=https://oauth2.googleapis.com/token
REACT_APP_TOKEN_REVOKE=https://oauth2.googleapis.com/revoke
REACT_APP_REDIRECTURI=http://localhost:3000
REACT_APP_CLIENT_SECRET=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
REACT_APP_SCOPE='email openid profile'
IAuthContext¶
A continuación se muestra el objeto que retorna useReactAuth()
que provee estos valores;
export interface IAuthContext {
token: string;
logOut: (_state?: string, _logoutHint?: string) => void;
login: (_state?: string) => void;
refreshAccessToken: (_initial?: boolean, _force?: boolean) => void;
editProfile: () => void; //use only for AD B2C
error: string | null;
tokenData?: TTokenData; //accessToken decoded
idTokenData?: TTokenData; //idToken decoded
idToken?: string;
loginInProgress: boolean;
}
AuthProvider¶
import { AuthProvider, TAuthConfig } from "@architecture-it/react-auth";
const authConfig : TAuthConfig={
//my configuration
clientId="";
authorizationEndpoint="";
//....
}
return (
<StyleSystemProvider>
<AuthProvider authConfig={authConfig}>
<Main>
<ErrorBoundary>
<AppRoutes />
</ErrorBoundary>
</Main>
</AuthProvider>
</StyleSystemProvider>
);
useReactAuth¶
Este hook permite acceder a la información de token, el idToken, el tokenData, el idTokenData, así como metodos para refrescar el token, cerrar sesión, iniciar sesión y editar el perfil (Sólo adb2c).
import { useReactAuth } from "@architecture-it/react-auth";
function Home() {
const { token , tokenData } = useReactAuth();
return (
<>
{token ? (
<Box className={styles.page} data-testid="home-page">
<Typography className={styles.text} data-testid="text" variant="h1">
<span className={styles.span}>Hola</span> {tokenData?.name}!
</Typography>
</Box>
) : (
<Box className={styles.page} data-testid="home-page">
<Typography className={styles.text} data-testid="text" variant="h2">
Por favor inicia sesión para ver la información de usuario.
</Typography>
</Box>
)}{" "}
</>
);
}
Important
Cosas a tener en cuenta:
Para la adaptacion a azureB2C que manejamos hoy en la compañia, fue necesario agregar customPolicies en el modelo de configuracion. Para la utilizacion de customPolicies hay que tener en cuenta que:
- si usa customPolicies se asume que utiliza Azure B2C
- Si usa customPolicies tendra disponible el editProfile ya que es exclusivo de dicho idp.
- Si usa customPolicies no se debe agregar los endpoint de token, logout y revoke.
- Los endpoint logout y revoke no son compatibles, es posible que solo debas utilizar uno.
- Se agrego el ClientSecret para que permita conexiones
Migración desde architecture-it/azure-b2c¶
Frente a la disponibilización de una nueva librería multiprovider para proyectos frontend, aquellas aplicaciones que utilizan @architecture-it/azure-b2c
deberán migrar a @architecture-it/react-auth
.
Para ello se describen a continuación los pasos a seguir para realizar la migración de forma correcta y configurar nuevamente el provider de autenticación.
Paso 1 - Eliminar Azure B2C¶
En primera instancia se deberá eliminar todas las configuraciones relacionadas a la librería @architecture-it/azure-b2c
correspondientes a la autenticación con B2C.
- Desinstalar architecture-it/azure-b2c.
- Eliminar archivo msalInstance.ts.
- Eliminar el provider de MSAL que se encuentra en
App.tsx
y la instancia de msal que se le pasa por parámetro desdeindex.tsx
.
Paso 2 - Instalar React Auth¶
Luego de eliminar las configuraciones relacionadas con la librería anterior, se deberá instalar la nueva librería:
// Usar manejador de paquetes correspondiente a su aplicación (pnpm, npm)
pnpm add @architecture-it/react-auth
Paso 3 - Configuraciones¶
Con la librería ya instalada se detallan a continuación las configuraciones que se deben realizar para su correcto funcionamiento:
-
Agregar como wrapper general el provider de autenticación en el archivo principal de la aplicación (por lo general App.tsx).
... // other imports import { AuthProvider } from "@architecture-it/react-auth"; export default function App() { return ( <AuthProvider> <Main> ... <AppRoutes /> ... </Main> </AuthProvider> ); }
-
Agregar las variables de entorno de acuerdo al provider de autenticación que se quiera utilizar, en este ejemplo se configurará Azure B2C:
# AUTH
REACT_APP_CLIENT_ID=token-client-id
REACT_APP_REDIRECTURI=http://localhost:3000
REACT_APP_AUTH_DOMAIN=url-auth-domain
REACT_APP_SCOPE=openid profile offline_access
REACT_APP_B2C_SIGNUPSIGNIN=B2C_1A_SIGNUP_SIGNINAAD
REACT_APP_B2C_FORGOTPASSWORD=B2C_1A_PASSWORDRESET
REACT_APP_B2C_EDITPROFILE=B2C_1A_PROFILEEDIT
!!! important "Importante"
De acuerdo al provider que se quiera configurar, las variables de entorno que se deben agregar difieren. Se recuerda que en el apartado [Environment](https://architecture-it.github.io/docs/Platform/Front/Librerias/react-auth/#enviroment) se explica.
-
Modificar el interceptor de los servicios, por el nuevo que se deberá importar desde la librería react-auth. Si utilizan los templates disponibilizados por Arquitectura en su aplicación, los archivos de servicios utilizan el interceptor de axios bajo la función
addResponseInterceptorRefreshToken
a la que se le pasa como parámetro la instancia de msal que previamente eliminamos.Esta función deberá ser reemplazada por
addResponseInterceptorAxios
como se muestra a continuación:import { addResponseInterceptorAxios } from "@architecture-it/react-auth"; import { ServiceBase } from "@architecture-it/core"; import env from "@architecture-it/react-env"; import axios from "axios"; ... class _UserService extends ServiceBase { constructor() { super(BASE_URL); addResponseInterceptorAxios(this.client, axios); } ... } const UserService = new _UserService(); export default UserService;
-
Reemplazar los hooks y componentes que utilicen en la aplicación provenientes de
azure-b2c
como puede ser el caso del hookuseUser()
o los componentes<UserAvatar />
o<SidebarWrapper />
. Su importación deberá ser actualizada desde la librería react-auth.
useReactAuth
¶
//index.tsx
import { useReactAuth } from "@architecture-it/react-auth";
function Home() {
const { token , tokenData } = useReactAuth();
return (
<>
{token ? (
<Box className={styles.page} data-testid="home-page">
<Typography className={styles.text} data-testid="text" variant="h1">
<span className={styles.span}>Hola</span> {tokenData?.name}!
</Typography>
</Box>
) : (
<Box className={styles.page} data-testid="home-page">
<Typography className={styles.text} data-testid="text" variant="h2">
Por favor inicia sesión para ver la información de usuario.
</Typography>
</Box>
)}{" "}
</>
);
}
Componentes Visuales¶
SidebarWrapper¶
Abstracción del Sidebar del Stylesystem, tiene dos propiedades aparte authenticateRoutes
y unauthenticatedRoutes
.
El objeto authenticatedRoutes tiene los mismos del SidebarItemProp ( el que recibe el Sidebar) pero se le agrega una propiedad más que es isAuthorized, obligatorio por si es necesario manejar roles y permisos especificos en el sidebar.
Uso Habitual
<SidebarWrapper
authenticatedRoutes={[
{
item: "Item que se ve autenticado",
onClick: () => {
if (pathname !== "/") {
navigate("");
}
handleClose();
},
selected: pathname === "/",
className: styles.listItem,
divider: true,
isAuthorized: true,
},
{
item: "Administración de Usuarios",
onClick: () => {
navigate("/person");
handleClose();
},
className: styles.listItem,
//Aca se puede colocar un hook o funcion que determine si está autorizado o no
isAuthorized: true,
},
]}
open={open}
onClose={handleClose}
onOpen={handleOpen}
/>
UserAvatar¶
- Component that show and handle login and logout.
- Shows only an icon on determinate viewport
(max-width:425px)
Componente que dispone internamente el login y el logout.
Esta hecho para ser usado en el navBar en principio pero nada limita utilizarlo en otro lugar.
En determinado viewport ( (max-width:425px)
) solo muestra un icono
//layout
<Header onClickButton={handleOpen}>
<UserAvatar />
</Header>
!IMPORTANTE! Cosas a tener en cuenta: Para la adaptacion a azureB2C que manejamos hoy en la compañia, fue necesario agregar customPolicies en el modelo de configuracion. Para la utilizacion de customPolicies hay que tener en cuenta que:
- si usa customPolicies se asume que utiliza Azure B2C
- Si usa customPolicies tendra disponible el editProfile ya que es exclusivo de dicho idp.
- Si usa customPolicies no se debe agregar los endpoint de token, logout y revoke.
- Los endpoint logout y revoke no son compatibles, es posible que solo debas utilizar uno.
- Se agrego el ClientSecret para que permita conexiones
Casos avanzados¶
Agregar query Params al login¶
Agregando simplemente una variable de entorno en tu archivo .env
con el prefijo REACT_APP_EXTRA_AUTH_PARAM_
.
Se construye d ela siguiente manera:
REACT_APP_EXTRA_AUTH_PARAM_{NOMBRE_DE_PARAMETRO}=VALOR
Por lo que daría cómo resultado el siguiente queryParam
: https://...?{NOMBRE_DE_PARAMETRO}=VALOR
Casos de Uso¶
Login directo con Azure:
Agregando el siguiente valor en el archivo .env
:
REACT_APP_EXTRA_AUTH_PARAM_DOMAIN_HINT=Andreani
Va a bypassear el login y va a redirigir directamente al login de Azure (microsoft) con el dominio de Azure B2C de Andreani.