Skip to content

Commit

Permalink
doc(readme): add migration guide and better readme
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-chervet committed Apr 1, 2022
1 parent f1501b3 commit 562a943
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 67 deletions.
173 changes: 173 additions & 0 deletions MIGRATION_GUIDE_V3_TO_V5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Migrate from v3 to v5

V4 is a complete rewrite. It uses the libraries ["App-AuthJS"](https://github.com/openid/AppAuth-JS) instead of oidc-client.
In the v4 we have chosen to remove a lot the surface API in order to simplify usage and enforce security.

- Packages
- [`@axa-fr/react-oidc-context`](./packages/context#readme.md) [![npm version](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-context.svg)](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-context)
- [`@axa-fr/vanilla-oidc`](./packages/vanilla#readme.md) [![npm version](https://badge.fury.io/js/%40axa-fr%2Fvanilla-oidc.svg)](https://badge.fury.io/js/%40axa-fr%2Fvanilla-oidc)
- [`@axa-fr/react-oidc-context-fetch`](./packages/context-fetch#readme.md) [![npm version](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-context-fetch.svg)](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-context-fetch) **Deprecated in v4**
- [`@axa-fr/react-oidc-redux`](./packages/redux#readme.md) [![npm version](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-redux.svg)](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-redux) **Deprecated in v4 : use react-oidc-context which works with redux and in fact does not use any react context**
- [`@axa-fr/react-oidc-redux-fetch`](./packages/redux-fetch#readme.md) [![npm version](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-redux-fetch.svg)](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-redux-fetch) **Deprecated in v4**
- [`@axa-fr/react-oidc-fetch-observable`](./packages/fetch-observable#readme.md) [![npm version](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-fetch-observable.svg)](https://badge.fury.io/js/%40axa-fr%2Freact-oidc-fetch-observable) **Deprecated in v4**

Migration PullRequest sample : https://github.com/samuel-gomez/react-starter-toolkit/pull/36


Main provider component have been renamed
```javascript
import { AuthenticationProvider } from '@axa-fr/react-oidc-context';

// old v3

<AuthenticationProvider configuration={oidcConfiguration} loggerLevel={oidcLog.DEBUG}>
</AuthenticationProvider>

// in v4 become

import { OidcProvider } from '@axa-fr/react-oidc-context';

//loggerLevel : Logger property has been removed in v4
<OidcProvider configuration={oidcConfiguration}>
</OidcProvider>
```

Provider properties have changed, you need to keep only required properties for v4 else it won't work.
```javascript
// old v3
const propTypes = {
notAuthenticated: PropTypes.elementType, // react component displayed during authentication
notAuthorized: PropTypes.elementType, // react component displayed in case user is not Authorised
authenticating: PropTypes.elementType, // react component displayed when about to redirect user to be authenticated
callbackComponentOverride: PropTypes.elementType, // react component displayed when user is connected
sessionLostComponent: PropTypes.elementType, // react component displayed when user loose authentication session
configuration: PropTypes.shape({
client_id: PropTypes.string.isRequired, // oidc client configuration, the same as oidc client library used internally https://github.com/IdentityModel/oidc-client-js
redirect_uri: PropTypes.string.isRequired,
response_type: PropTypes.string.isRequired,
scope: PropTypes.string.isRequired,
authority: PropTypes.string.isRequired,
silent_redirect_uri: PropTypes.string.isRequired,
automaticSilentRenew: PropTypes.bool, //optional, by default to true
loadUserInfo: PropTypes.bool, //optional, by default to true
post_logout_redirect_uri: PropTypes.string, // optional
metadata: PropTypes.shape({
issuer: PropTypes.string,
jwks_uri: PropTypes.string,
authorization_endpoint: PropTypes.string,
token_endpoint: PropTypes.string,
userinfo_endpoint: PropTypes.string,
end_session_endpoint: PropTypes.string,
revocation_endpoint: PropTypes.string,
introspection_endpoint: PropTypes.string,
}),
}).isRequired,
isEnabled: PropTypes.bool, // enable/disable the protections and trigger of authentication (useful during development).
loggerLevel: PropTypes.number,
logger: PropTypes.shape({
info: PropTypes.func.isRequired,
warn: PropTypes.func.isRequired,
error: PropTypes.func.isRequired,
debug: PropTypes.func.isRequired,
}),
UserStore: PropTypes.func,
};

// new v4
const propTypes = {
loadingComponent: PropTypes.elementType, // you can inject your own loading component
sessionLostComponent: PropTypes.elementType, // you can inject your own session lost component
authenticating: PropTypes.elementType, // you can inject your own authenticationg component
callbackSuccessComponent: PropTypes.elementType, // you can inject your own call back success component
callbackErrorComponent: PropTypes.elementType, // you can inject your own call back error component
serviceWorkerNotSupportedComponent: PropTypes.elementType, // you can inject your page that explain your require a more modern browser
configuration: PropTypes.shape({
client_id: PropTypes.string.isRequired, // oidc client id
redirect_uri: PropTypes.string.isRequired, // oidc redirect url
silent_redirect_uri: PropTypes.string, // Optional activate silent-signin that use cookies between OIDC server and client javascript to restore sessions
scope: PropTypes.string.isRequired, // oidc scope (you need to set "offline_access")
authority: PropTypes.string.isRequired,
refresh_time_before_tokens_expiration_in_second: PropTypes.number,
service_worker_relative_url: PropTypes.string,
service_worker_only: PropTypes.boolean, // default false
extras: StringMap|undefined // ex: {'prompt': 'consent', 'access_type': 'offline'} list of key/value that are send to the oidc server (more info: https://github.com/openid/AppAuth-JS)
}).isRequired
};
```


Manage Oidc actions and informations

```javascript

// old v3
import { useReactOidc } from '@axa-fr/react-oidc-context';
const { isEnabled, login, logout, oidcUser, events } = useReactOidc();


// new v45
import { useOidc, useOidcAccessToken, useOidcIdToken, useOidcUser } from '@axa-fr/react-oidc-context';

const { login, logout, isAuthenticated} = useOidc(); // login and logout return a Promise
const{ oidcUser, oidcUserLoadingState } = useOidcUser(); // Return user_info endpoint data
const{ accessToken, accessTokenPayload } = useOidcAccessToken(); // Contain access_token metadata acess_token is a jwk
const{ idToken, idTokenPayload } = useOidcIdToken(); // contain IDToken metadata

```
```javascript

// old v3
import { withFetchRedirectionOn401,
withFetchSilentAuthenticateAndRetryOn401,
withFetchRedirectionOn403,
withAuthentication } from '@axa-fr/react-oidc-context-fetch';


// new v4
import { withOidcFetch } from '@axa-fr/react-oidc-context';


// withFetchRedirectionOn401 : removed, you have to implement your own 401 management
// withFetchSilentAuthenticateAndRetryOn401 : removed, not necessary in v4 token are in auto refresh mode only
// withFetchRedirectionOn403 : removed, you have to implement your own 403 management
// withAuthentication : removed

// withFetchToken in v3 have been rename to withOidcFetch and set inside '@axa-fr/react-oidc-context' package
withOidcFetch(</MyComponent/>)


```

If you need a very secure mode where refresh_token and access_token will be hide behind a service worker that will proxify requests.

Add a copy task in order to install and stay up to date an Oidc Service Worker.
The only file you should edit is "OidcTrustedDomains.js" which will never be erased with the configuration bellow.

```sh
#package.json
{
"scripts": {
"copy": "copyfiles -f ./node_modules/@axa-fr/react-oidc-context/dist/OidcServiceWorker.js ./public && copyfiles -f -s ./node_modules/@axa-fr/react-oidc-context/dist/OidcTrustedDomains.js ./public",
"start:server": "react-scripts start",
"build:server": "npm run copy && react-scripts build",
"prepare": "npm run copy"
}
}
```

Then edit OidcTrustedDomains.js in "public" folder for your need

```javascript
// OidcTrustedDomains.js
// Add here trusted domains, access tokens will be send to
const trustedDomains = {
default:["http://localhost:4200"],
};
```


In case v4 does not implement all features that you are using or this migration guide enought complete.

Please make issues or PullRequest in order to help to complete it !


24 changes: 24 additions & 0 deletions MIGRATION_GUIDE_V4_TO_V5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Migrate from v4 to v5

V5 is a small refactor renaming.

```javascript

// old v4

const { login, logout, isLogged} = useOidc();

// in v4 become

const { login, logout, isAuthenticated} = useOidc();
```

Provider properties have changed, you need to keep only required properties for v4 else it won't work.
```javascript
// old v3
const{ oidcUser, isOidcUserLoading, isLogged } = useOidcUser();

// new v4
const{ oidcUser, oidcUserLoadingState } = useOidcUser();
```

45 changes: 23 additions & 22 deletions packages/context/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ const DisplayAccessToken = () => {
<div className="card-body">
<h5 className="card-title">Access Token</h5>
<p style={{color:'red', "backgroundColor": 'white'}}>Please consider to configure the ServiceWorker in order to protect your application from XSRF attacks. ""access_token" and "refresh_token" will never be accessible from your client side javascript.</p>
{accessToken != null && <p className="card-text">{JSON.stringify(accessToken)}</p>}
{<p className="card-text">{JSON.stringify(accessToken)}</p>}
{accessTokenPayload != null && <p className="card-text">{JSON.stringify(accessTokenPayload)}</p>}
</div>
</div>
Expand All @@ -262,7 +262,7 @@ const DisplayIdToken =() => {
<div className="card text-white bg-info mb-3">
<div className="card-body">
<h5 className="card-title">ID Token</h5>
{idToken != null && <p className="card-text">{JSON.stringify(idToken)}</p>}
{<p className="card-text">{JSON.stringify(idToken)}</p>}
{idTokenPayload != null && <p className="card-text">{JSON.stringify(idTokenPayload)}</p>}
</div>
</div>
Expand All @@ -275,29 +275,30 @@ const DisplayIdToken =() => {
## How to get User Information : Hook method
```javascript
import { useOidcUser } from '@axa-fr/react-oidc-context';
import { useOidcUser, UserStatus } from '@axa-fr/react-oidc-context';
const DisplayUserInfo = () => {
const{ oidcUser, isOidcUserLoading } = useOidcUser();
if(isOidcUserLoading !== UserStatus.Loaded) {
return <p>User Information are loading</p>
}
if(!oidcUser){
return <p>you are not authenticated</p>
}
return (
<div className="card text-white bg-success mb-3">
<div className="card-body">
<h5 className="card-title">User information</h5>
<p>{oidcUser == null && "You are not logged" }</p>
{oidcUser != null && <p className="card-text">{JSON.stringify(oidcUser)}</p>}
</div>
</div>
)
const{ oidcUser, oidcUserLoadingState } = useOidcUser();
switch (oidcUserLoadingState){
case UserStatus.Loading:
return <p>User Information are loading</p>;
case UserStatus.Unauthenticated:
return <p>you are not authenticated</p>;
case UserStatus.LoadingError:
return <p>Fail to load user information</p>;
default:
return (
<div className="card text-white bg-success mb-3">
<div className="card-body">
<h5 className="card-title">User information</h5>
<p className="card-text">{JSON.stringify(oidcUser)}</p>
</div>
</div>
);
}
};
```
# Service Worker Support
Expand Down
44 changes: 20 additions & 24 deletions packages/context/src/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
import React from 'react';

import {OidcSecure, useOidc, useOidcAccessToken, useOidcIdToken, useOidcUser} from "./oidc";
import {UserStatus} from "./oidc/User";
import {OidcSecure, useOidcAccessToken, useOidcIdToken, useOidcUser, UserStatus} from "./oidc";


const DisplayUserInfo = () => {
const{ oidcUser, oidcUserLoadingState } = useOidcUser();

if(oidcUserLoadingState === UserStatus.Loading) {
return <p>User Information are loading</p>
}

if(oidcUserLoadingState === UserStatus.LoadingError) {
return <p>User Information loading errored.</p>
}

if(!oidcUser){
return <p>you are not authenticated</p>
switch (oidcUserLoadingState){
case UserStatus.Loading:
return <p>User Information are loading</p>;
case UserStatus.Unauthenticated:
return <p>you are not authenticated</p>;
case UserStatus.LoadingError:
return <p>Fail to load user information</p>;
default:
return (
<div className="card text-white bg-success mb-3">
<div className="card-body">
<h5 className="card-title">User information</h5>
<p className="card-text">{JSON.stringify(oidcUser)}</p>
</div>
</div>
);
}

return (
<div className="card text-white bg-success mb-3">
<div className="card-body">
<h5 className="card-title">User information</h5>
<p>{oidcUser == null && "You are not logged" }</p>
{oidcUser != null && <p className="card-text">{JSON.stringify(oidcUser)}</p>}
</div>
</div>
)
};

export const Profile = () => {
Expand All @@ -51,7 +47,7 @@ const DisplayAccessToken = () => {
<div className="card-body">
<h5 className="card-title">Access Token</h5>
<p style={{color:'red', "backgroundColor": 'white'}}>Please consider to configure the ServiceWorker in order to protect your application from XSRF attacks. "access_token" and "refresh_token" will never be accessible from your client side javascript.</p>
{accessToken != null && <p className="card-text">Access Token: {JSON.stringify(accessToken)}</p>}
{<p className="card-text">Access Token: {JSON.stringify(accessToken)}</p>}
{accessTokenPayload != null && <p className="card-text">Access Token Payload: {JSON.stringify(accessTokenPayload)}</p>}
</div>
</div>
Expand All @@ -70,7 +66,7 @@ const DisplayIdToken =() => {
<div className="card text-white bg-info mb-3">
<div className="card-body">
<h5 className="card-title">ID Token</h5>
{idToken != null && <p className="card-text">IdToken: {JSON.stringify(idToken)}</p>}
{<p className="card-text">IdToken: {JSON.stringify(idToken)}</p>}
{idTokenPayload != null && <p className="card-text">IdToken Payload: {JSON.stringify(idTokenPayload)}</p>}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/context/src/oidc/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { withOidcSecure, OidcSecure } from "./OidcSecure";
export { useOidcUser } from "./User";
export { useOidcUser, UserStatus } from "./User";
export { useOidc, useOidcAccessToken, useOidcIdToken } from "./ReactOidc";
export { withOidcFetch, fetchWithToken } from "./FetchToken";
export { OidcProvider } from "./OidcProvider";
Loading

0 comments on commit 562a943

Please sign in to comment.