Sign with Redirect
Once the authentication is complete, we will get the user's JoyID information, such as username, address, credential, etc. In this guide, we will continue our previous journey in Auth with Redirect by signing a challenge after the authentication is complete.
To redirect to JoyID App to sign a challenge, we need to do the following steps:
Step 1: Save authentication info
In the previous guide, we have already authenticated the user with JoyID, and we have got the user's JoyID information. Now we need to save the user's JoyID information. We can save it in the local storage, or in the state of the React component, or in the Vuex store of the Vue app, etc.
import * as React from 'react';
import { authWithRedirect, authCallback } from '@joyid/core';
import './style.css';
export default function App() {
const [authInfo, setAuthInfo] = React.useState(null);
const isRedirectFromJoyID = new URL(location.href).searchParams.has(
'joyid-redirect'
);
const authOnClick = async () => {
authWithRedirect({
redirectURL: location.href,
name: 'Awesome App',
challenge: 'Sign this for me',
logo: 'https://reactjs.org/logo-180x180.png',
});
};
React.useEffect(() => {
if (isRedirectFromJoyID) {
const authRes = authCallback();
if (authRes.error == null && authRes.type === 'Auth') {
setAuthInfo(authRes)
}
}
}, []);
return (
<div>
<h1>Hello JoyID!</h1>
<button onClick={authOnClick}>Auth With JoyID</button>
</div>
);
}Step 2: Sign the challenge
After the authentication is complete, we need to add a button element and listen to the click event. When the user clicks the button, we will call the signWithRedirect function to sign the challenge with the user's JoyID.
Note that address is required in the signWithRedirect function. You can only sign the challenge with the user's JoyID if you know the user's address. The address is included in authentication info.
Verify the credential before signing the challenge
import * as React from 'react';
import {
authCallback,
authWithRedirect,
signCallback,
signWithRedirect,
} from '@joyid/core';
import './style.css';
export default function App() {
...
const signOnClick = async () => {
signWithRedirect({
redirectURL: location.origin + '/',
name: 'Awesome App',
challenge,
logo: 'https://reactjs.org/logo-180x180.png',
address: authInfo?.address,
state,
});
};
...
return (
...
<button onClick={signOnClick}>Sign With JoyID</button>
...
);
}Step 3: Get redirected data
After the user signed with JoyID App, the user will be redirected back to your App with the result in the URL query string. We need to call signCallback function in your redirected page to get the result.
In this step, we save all UI states and pass to the JoyID App via the state parameter of signWithRedirect function. When the signing is done, the same UI states are returned via the signCallback function, which keeps our UI continuous. But this is not the only way to maintain UI continuity after redirection, you can also save UI state to localStorage or server side, or even just ignore UI continuity.
import * as React from 'react';
import {
authCallback,
authWithRedirect,
signCallback,
signWithRedirect,
} from '@joyid/core';
import './style.css';
const initState = {
authInfo: null,
challenge: 'Sign this for me',
};
type Action = {
type: 'challenge' | 'authInfo';
payload: any;
};
const reducer = (state: typeof initState, action: Action): typeof initState => {
const { type, payload } = action;
switch (type) {
case 'challenge': {
return {
...state,
challenge: payload,
};
}
case 'authInfo': {
return {
...state,
authInfo: payload,
};
}
default: {
return state;
}
}
};
export default function App() {
const isRedirectFromJoyID = new URL(location.href).searchParams.has(
'joyid-redirect'
);
const [state, dispatch] = React.useReducer(reducer, initState);
const { challenge, authInfo } = state;
const authOnClick = async () => {
authWithRedirect({
redirectURL: location.origin + '/',
name: 'Awesome App',
challenge: 'Sign this for me',
logo: 'https://reactjs.org/logo-180x180.png',
state,
});
};
const signOnClick = async () => {
signWithRedirect({
redirectURL: location.origin + '/',
name: 'Awesome App',
challenge,
logo: 'https://reactjs.org/logo-180x180.png',
address: authInfo?.address,
state,
});
};
React.useEffect(() => {
if (isRedirectFromJoyID) {
const authRes = authCallback();
if (authRes.error == null && authRes.type === 'Auth') {
dispatch({ type: 'authInfo', payload: authRes.data });
}
const signRes = signCallback();
if (signRes.error == null && signRes.type === 'SignMessage') {
const { state, ...data } = signRes.data;
const { authInfo, challenge } = state as typeof initState;
dispatch({ type: 'challenge', payload: challenge });
dispatch({ type: 'authInfo', payload: authInfo });
// see console for details
console.log(data);
}
}
}, []);
return (
<div>
<h1>Hello JoyID!</h1>
{authInfo ? null : (
<button onClick={authOnClick}>Auth With JoyID</button>
)}
{authInfo ? (
<div>
<textarea
value={challenge}
onChange={(e) =>
dispatch({
type: 'challenge',
payload: e.target.value,
})
}
/>
<button onClick={signOnClick}>Sign With JoyID</button>
</div>
) : null}
</div>
);
}signCallback function, please check the API Reference.