AppAuth JS integration in React
Tags: appauth, react, security, openidconnect
Published: 2020-08-10 12:28:03

---
title: AppAuth JS integration in React
published: true
description: Integrate OpenID Connect OAuth 2.0 Authorization Code PKCE Flow into your React Application using AppAuth JS
tags: #appauth #react #security #openidconnect
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9h5wn046bk1jx5bjfady.jpg
---

:heart: What is OpenID Connect and why Authorization Code flow for React(SPA) Application?
:point_right: [Check my blog here for answer](https://dev.to/kdhttps/the-best-security-for-single-page-applications-spa-openid-connect-oauth-2-0-authorization-code-pkce-flow-544p)

:dart: The [AppAuth JS](https://github.com/openid/AppAuth-JS) is the best library to integrate OpenID Connect Authorization Code PKCE Flow at your React or any single page application technology.

:fire: Here is React JS code with AppAuth JS integration.

{% github kdhttps/appauth-react %}

## :books: Let's Go Step by Step

Before start, You need to create an OP Client using your OP Admin Panel. Setup client, client id, client secret, redirect login URL, response_type = code, grant_type = authorization_code and refresh_token(as per your need).

> `https://server.com` is just for example. You need to use your OP server URL.

![Appauth-authorization-code-pkce-flow](https://dev-to-uploads.s3.amazonaws.com/i/zgds6m0n0ykpq30oihlb.png)

## There are 3 main steps

1. Authorization Request to OP Server
2. Get a `code` from URL and get `access_token`
3. Get user info using access_token

## :star: Authorization Request to OP Server

The first task is to make the authorization requests to the OpenID Connect server.

Below all code in one file. Please check my [appauth-react](https://github.com/kdhttps/appauth-react) repo for whole code.

**1.** First step is to initialize the `RedirectRequestHandler`. This object is responsible to handle the redirect task. It needs 4 Parameters.

    A. Define Storage
    B. URL Parameter Parser to get query params
    C. Current location or URL
    D. Crypto Method - to generate code_verifier and code_challenge

```javascript
import {
    RedirectRequestHandler,
    LocalStorageBackend, DefaultCrypto
} from '@openid/appauth';
import { NoHashQueryStringUtils } from './noHashQueryStringUtils';

const authorizationHandler = 
    new RedirectRequestHandler(
       new LocalStorageBackend(), 
       new NoHashQueryStringUtils(), 
       window.location, 
       new DefaultCrypto()
);
```

**2.** Second step is to configure query param parser

It is for URL parsing. Default it assume that you have **#** in URL. If you worked on OLD Angular.js then it uses **#** for client-side routing. 

If you want to change this method then you can easily overwrite the method like below code:

```javascript
import {BasicQueryStringUtils} from '@openid/appauth';

export class NoHashQueryStringUtils extends BasicQueryStringUtils {
    parse(input, useHash) {
        return super.parse(input, false /* never use hash */);
    }
}
```

**3.** Third Step is AppAuth needs your OP Server configuration information that is provided by endpoint `https://server.com/.well-known/openid-configuration`.

Below AppAuthJS code help you hit, get info, and stored info in local storage. This information is internally used by AppAuthJS.

You just need to pass two parameters.
    
    A. Your OP Server URL: for example: https://server.com
    B. FetchRequester: It is Javascript Fetch API to make an HTTP Request to OP configuration endpoint. If you miss this parameter, It will use JQuery and we don't want to use JQuery in React Application.

```javascript   
import {
    AuthorizationServiceConfiguration,
    FetchRequestor,
} from '@openid/appauth';

AuthorizationServiceConfiguration.fetchFromIssuer([your_op_seerver_url], new FetchRequestor())
            .then((response) => {
                console.log(response)
                // You need to add auth request code here
            })
            .catch(error => {
                setError(error);
            });
```

**4.** Make an auth request. Below is a combined code with configuration info step.

```javascript       
 AuthorizationServiceConfiguration.fetchFromIssuer(environment.OPServer, new FetchRequestor())
            .then((response) => {
                const authRequest = new AuthorizationRequest({
                    client_id: 'your_client_id',
                    redirect_uri: 'your_redirect_login_url',
                    scope: 'openid email profile',
                    response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
                    // extras: environment.extra
                });

               // Please check next point 5 for this.
authorizationHandler.performAuthorizationRequest(response, authRequest);

            })
            .catch(error => {
                setError(error);
            });

```

Pass extra parameters using **extra** property.

**5.** Redirect to OP for Auth

It needs two parameters first configuration information and second is auth Request.

Use the below code for this. Once this code executes, it will redirect you to OP Server.

```javascript
authorizationHandler.performAuthorizationRequest(response, authRequest);
```

#### :star: OP Server will authenticate the user and redirect back to your side with **code** in URL. Let's assume you configure redirect login URL is `https://client.com/callback`. Please check my [appauth-react](https://github.com/kdhttps/appauth-react) repo for Flow GIF and code. You will get an idea.

## :star: Get a `code` from URL and get `access_token`

Let's assume URL in the browser is like now `https://client.com/callback?code=[code_send_by_op_server]`

we are now on `/callback` react-router. so you need to handle the next operations on this route.

Note: You can combine these steps into one file. Currently, for an easy explanation, I am doing it in different files.  

**1.** The first step you need to configure the `AuthorizationNotifier` which will trigger when you want to process code(the code from URL).

```javascript
import {
    AuthorizationServiceConfiguration,
    RedirectRequestHandler,
    AuthorizationNotifier,
    FetchRequestor, LocalStorageBackend, DefaultCrypto
} from '@openid/appauth';

import {NoHashQueryStringUtils} from './noHashQueryStringUtils';

const authorizationHandler = new RedirectRequestHandler(new LocalStorageBackend(), new NoHashQueryStringUtils(), window.location, new DefaultCrypto());

const notifier = new AuthorizationNotifier();
        authorizationHandler.setAuthorizationNotifier(notifier);

notifier.setAuthorizationListener((request, response, error) => {
    // response object returns code which is in URL i.e. response.code
    // request object returns code_verifier i.e request.internal.code_verifier
    // you will need to add here token request process
}
```

**2.** Above notifier only trigger when you want it using below code:

```javascript
authorizationHandler.completeAuthorizationRequestIfPossible()
```

Once this code executes, it will trigger the notifier and in the response object, you will get code from URL.

**3.** Request for access_token 

The below code is inside the notifier.

    A. First, you need to create a token request object
    B. Again get configuration information
    C. Hit `/token` endpoint and get token

```javascript

const tokenHandler = new BaseTokenRequestHandler(new FetchRequestor());

notifier.setAuthorizationListener((request, response, error) => {
            console.log('Authorization request complete ', request, response, error);
            if (response) {
                console.log(`Authorization Code  ${response.code}`);

                let extras = null;
                if (request && request.internal) {
                    extras = {};
                    extras.code_verifier = request.internal.code_verifier;
                }

                // A. First, you need to create a token request object
                const tokenRequest = new TokenRequest({
                    client_id: 'your_client_id',
                    redirect_uri: 'your_redirect_login_url',
                    grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
                    code: response.code,
                    extras
                });

                // B. Again get configuration information
AuthorizationServiceConfiguration.fetchFromIssuer(environment.OPServer, new FetchRequestor())
                    .then((oResponse) => {
                        const configuration = oResponse;
                        // C. Hit `/token` endpoint and get token
                        return tokenHandler.performTokenRequest(configuration, tokenRequest);
                    })
                    .then((oResponse) => {
                        localStorage.setItem('access_token', oResponse.accessToken);
                        // do operation now as per your need
                        props.history.push('/profile');
                    })
                    .catch(oError => {
                        setError(oError);
                    });
            }
        });
```

Now, you have `access_token`, you can store it in localStorage and use it in the whole application.

## :star: Get user info using access_token

You don't need AppAuthJS for this task. You just need to hit the `/userinfo` endpoint of your OP Server and it will return you the user information.

> `https://server.com` is just for example. You need to use your OP server URL.

let's assume we are now on `/profile` page.

```javascript

const fetchUserInfo = async (token) => {
    const res = await fetch(`https://server.com/userinfo`, {
        headers: {
            authorization: `Bearer ${token}`
        }
    });
    return res.json();
};

export const Profile = () => {
    const [userInfo, setUserInfo] = useState(null);

    useEffect(() => {
        const fetchToken = localStorage.getItem('access_token');
        fetchUserInfo(fetchToken)
            .then((info) => {
                console.log(info);
                setUserInfo(info);
            })
        return () => {
        }
    }, []);
  
  return (
  .....
  );
}
```

Done.

We just integrated AppAuth JS into React Application.

Please check my [appauth-react](https://github.com/kdhttps/appauth-react) repo for whole integration.

If you are on angular then please check my [appauth-angular](https://github.com/kdhttps/appauth-angular) repo.

You can integrate AppAuthJS in any client-side technology using the above steps.

Hope this will help !!!

#### #HappySharing #HappyHelping