we have created our own oauth 2 server with authorization code implementation from below code base. https://github.com/FrankHassanabad/Oauth2orizeRecipes
but we are trying to integrate oauth2 client authentication in web application which includes react router and flux implementation.
we looked into many git repositories but not getting any proper way to do this.
is there any implementation which points us to how it can be achieved?
Thanks again.
UPDATE
we are looking into below repositories, but still not clear on how we make things work. like where to merge auth and oauth logic and what things to make server/client side.
https://github.com/rackt/react-router/tree/master/examples/auth-flow
https://github.com/andreareginato/simple-oauth2
https://github.com/LearnBoost/superagent-oauth
https://github.com/zalando/superagent-oauth2-client
Here's how the application will look like: import React, { useState } from 'react' import Pizzly from 'pizzly-js' import Profile from './Profile' const App = () => { const [profile, setProfile] = useState() return ( <div className="App"> <h1>Hello!
There are two main things your React application needs to do to sign on a user: Get an access token from an authentication server. Send the access token to your backend server with each subsequent request.
import { Navigate } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const ProtectedRoute = ({ children }) => { const { user } = useAuth(); if (!user) { // user is not authenticated return <Navigate to="/" />; } return children; }; To redirect the user, we use the <Navigate /> component.
I'll attempt to explain my high level take authentication with react-router. You will need implementation on both server and client and there are a few decisions you need to make yourself. For this example I will be using redux for the flux library.
First you will need a mechanism to protect your routes, I do this with a higher order component like so:
// 'Components/requireAuthentication'
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import SignIn from './SignIn'
export default (ChildComponent) => {
class AuthenticatedComponent extends Component {
static propTypes = {
hasAuthToken: PropTypes.bool.isRequired
};
render () {
const { hasAuthToken } = this.props
return (hasAuthToken
? <ChildComponent {...this.props} />
: <SignIn />
)
}
}
const mapStateToProps = ({session}) => (session)
return connect(mapStateToProps)(AuthenticatedComponent)
}
The code here is quite simple, it exports a function that expects a react component as the only argument. This ChildComponent
is the component you want to protect.
The hasAuthToken
prop is the control here, if it is true then the ChildComponent
will be rendered, otherwise it will render SignIn
. Note, this process of rendering SignIn
is fine if you don't care about SEO but you may want to redirect the user to a sign-in route if you do care about search engines indexing your protected routes.
Finally AuthenticatedComponent
is connected to the redux store session
state but this could easily be switched out to use any other flux library of your choosing. Simply put, it is subscribing to changes on session
. If the hasAuthToken
changes in value, the component will be re-rendered if it is presently mounted.
Now for the routes:
import { Route } from 'react-router'
import Container from './Components/Container'
import Private from './Components/Private'
import requireAuthentication from './Components/requireAuthentication'
export default (
<Route path='/' component={Container}>
<Route path='private' component={requireAuthentication(Private)}>
<Route path='other' component={...} />
</Route>
</Route>
)
Here I am applying the requireAuthentication
method (the default exported method from the code above) with the component I want to protect. This will keep pages from being shown unless the redux store session.hasAuthToken
property is true and instead show the SignIn
component.
Other routes nested under the protected component will also be protected because of the way react-router composes the routes.
At a high level the SignIn
component should simply be a page with a normal <a href>
(i.e. not react-router Link
) to begin the Oauth2 handshake. The simple-oauth2 module has some nice examples on how to implement oauth2 server-side so I won't get into that here. If you're following those examples, it's the app.get('/auth', function (req, res) {})
endpoint you want to link the user to.
In the callback
endpoint you will want to persist the token
somehow (e.g. to your session (express-session will help out here) or to the database), then redirect the user back to your react app.
Now you'll need to get your session into the server-side redux store in preparation for it to be hydrated on the client. The redux docs explains how to do this on the Server Rendering page, specifically the Inject Initial Component HTML and State and The Client Side sections. At a minimum you'll need an object like this:
{
hasAuthToken: (typeof req.session.token !== 'undefined')
}
Of course your actual implementation will depend entirely on how you store the token and provide it to the server-side request.
Hopefully this will get you started. This same process can be used for other kinds of authentication as well by replacing the Oauth2 link with a username and password form that your server handles as an XHR.
Best of luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With