DEV Community

Discussion on: Critique My Plan: API Key for Authentication

Collapse
 
imthedeveloper profile image
ImTheDeveloper • Edited

Hi Tom,
Firstly thank you for the detailed response and efforts put into answering all of my questions. The time taken is appreciated!

To answer some of your assumptions made. I do not control the game code at all, however I can I inject anything post page render using my user script. This will allow me to control the way in which my API is accessed from the client, however I should probably make the assumption that anyone can see that code and make a request using whatever client e.g. postman.

I think it's interesting you mentioned JWT. I'm going to do some reading up on that vs oAuth2.

I think at the moment I'm toying with a key design decision:

  1. In the short term do I allow a user to generate a token from their user profile in my system (not the game) and they just then enter this in an injected form I place in the game. This can then be stored as a cookie with http only enabled as you suggested. The benefit here is mainly that I remove a bit of coding on my side for some aspects and also allows the user to revoke the token or regen quite easy. I see this route as being the easy/lazy route.

  2. Do I inject a form into the game where the user can enter their user/pass for my system tools, which in turn returns the packaged token and saves it within an encrypted cookie with http only again. This feels a bit more user friendly but also a bit more overhead on my implementation. I'm wondering since I have only the user script to access data (via javascript) whether I can even access a http only cookie. I assume you need to read the cookie to send it in the subsequent API calls? Or do you send the cookie in the request and the server reads it?

Alternatively I just store it in the web storage.

jwt flow
Source: auth0.com/docs/jwt

I've actually just read up on jwt some more on auth0 and it's offered some great validation of your reply. I think I'll go with generating a JWT and then have this stored on the client in their local storage. I'll create a new API route for login/creation of the JWT in my sails.js app and then build out a policy that does the checks against the supplied JWT. I can then just drop this policy in against my user script routes since I generate the javascript on the fly that is injected into the game pages.

Collapse
 
tom profile image
tom • Edited

I should probably make the assumption that anyone can see that code and make a request using whatever client e.g. postman.

Absolutely make this assumption. It’s that which makes me suggest using an HTTP-only, secure cookie: it defends it from code that knows what it’s looking for and where to look.

I think it's interesting you mentioned JWT. I'm going to do some reading up on that vs oAuth2.

This isn’t so much of a “vs” as two separate (complimentary) ideas. JWT is just a standard for creating and validating tokens. OAuth2 is a set of authentication protocols.

JWT is a totally logical choice for a token within an OAuth2 flow.

It’s not explicitly mentioned in the JWT docs but the recommended use of a JWT is in the Authorisation header, which is the same recommendation as in the OAuth2 Bearer spec (tools.ietf.org/html/rfc6750#sectio...).

I’m toying with a key design decision…

I won’t suggest anything specific but if there’s going to be a login form for the service, and an embedded login form, could they be the same form? (think iframes, CSP)

I'm wondering since I have only the user script to access data (via javascript) whether I can even access a http only cookie. I assume you need to read the cookie to send it in the subsequent API calls? Or do you send the cookie in the request and the server reads it?

The first step is setting the cookie from the server, using the Set-Cookie header (developer.mozilla.org/en-US/docs/W...).

After that, the browser does all this for you when you either (1) set withCredentials = true on the XMLHttpRequest (developer.mozilla.org/en-US/docs/W...) or (2) set credentials: 'include' if you’re using the fetch API (developer.mozilla.org/en-US/docs/W...).

It slurps up all the cookies for the origin it’s talking to and sends them along with the request automatically.

You don’t need your client side to be able read the cookie at all.

One other thing you could consider is writing a cookie that indicates that the user is logged in that can be read from JavaScript: that let’s you make decisions in your client-side code that don’t require “checking” with your API.

And I strongly suggest you don’t use local storage: you will have to write it against the origin of the game which makes it accessible to any and all other user scripts running.