2

I'm adding OAuth into my github clientside application. I have the final auth token being returned successfully, but I feel like I hacked my workflow.

Current Architecture Flow:

1) User clicks href link from component to hit the initial OAUTH route

2) Retrieve token from Github for user identity

3) Github redirects to my server route and my server route sends an additional POST to the /access_token request page with the client_secret, id and code from the above step.

4) Finally I redirect from the above route back to my UI and set a URL parameter in the process

5) In the componentDidMount I strip the final auth token from the window.url and set it in my state

Note: I plan on storing the token in Redux later, but this is the base level as to what I'm doing.

Actual Code

Server

app.get("/login", async (req, res) => {
  // Get the identity token from GitHub origin
  return await axios
    .post("https://github.com/login/oauth/access_token", {
      code: req.query.code,
      client_id: process.env.CLIENT_ID,
      client_secret: process.env.CLIENT_SECRET
    })
    .then(async resp => {
      // Little hack to parse out the query params into an object 
      let data = await url.parse("http://parse.com?" + resp.data, {
        parseQueryString: true
      }).query;

      res.redirect(
        url.format({
          pathname: Environment.getUrl(),
          query: {
            token: data.access_token
          }
        })
      );
    });
});

UI Authentication Component

export default class GithubAuthentication extends React.Component {
  state = {
    authToken: "DATA"
  };

  componentDidMount() {
    let currUrl = window.location.href;
    this.setState({ authToken: currUrl.split("token=")[1] });
  }

  render() {
    return (
      <React.Fragment>
        <a href="https://github.com/login/oauth/authorize?client_id=b5cd37110eb31620aad7">
          {this.state.authToken ? "Logout" : "Login With Github"}
        </a>
        <span>{this.state.authToken}</span>
      </React.Fragment>
    );
  }
}

Questions

1) The one thing I wasn't able to figure out was to make the href link a controlled component and actually hit the auth URL with something like SuperAgent or Axios. Instead, I'm forced to use this href link, not sure why.

2) Is this actually a sensible flow for getting the final auth token?

2 Answers 2

1

Regarding question 2, from a security standpoint, it is better to keep access token on server-side and never send the token to client-side.

I couldn't find good written resources, so I'd like to share this video which sums up how to deal with access token clearly.

https://www.youtube.com/watch?v=CHzERullHe8&list=PL78z2Z3ZApYcKb-GDQt6ikdN2EDqmKJrT&index=12&t=419s

Take away from the video

  • We still don't have a good way to securely store the token on the browser
  • By storing the access token on the server-side and using session cookie, you can minimize the risk of access token being compromised.

To actually implement this flow, you can use cookie-session to generate session. You can also use github-passport to simplify the implementation.

https://github.com/expressjs/cookie-session https://github.com/jaredhanson/passport-github

Sign up to request clarification or add additional context in comments.

Comments

0

1) I think you should reorganize your app so that you can use a component instead of an href link. You would know whether you're authenticated or not based on the value on the state property. This value can be passed as prop to your component which is where you would put the logic of authenticated ? "Logout" : "Login" or anything else.

2) the flow is OK but you have to make sure you do server side validation of the token since it's easy to just flip the switch on the UI and the pretend you're authenticated very easily.

2 Comments

I was getting cross-origin issues when using a component instead of href. Not quite sure why this is happening.
CORS issue happens if you make a js call to another server and that server is not allowing unsolicited calls from an unknown app which is on by default so your server should allow requests from your client domain in the Access-Control-Allow-Origin header

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.