Skip to content

Implement API Key authorization #534

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 11, 2016
Merged

Implement API Key authorization #534

merged 13 commits into from
Sep 11, 2016

Conversation

agrafix
Copy link
Contributor

@agrafix agrafix commented Sep 4, 2016

This basically implements #416 after a discussion with @dcoutts at MuniHac2016.

This PR introduces a new user management page which only admins and the user owning the account can access. There is a link to reset the password and a form to allocate a new api key or revoke existing keys. Keys are generated from random 512 bits and are stored hashed with sha256 in server. Users and programs can then set the header Authorization: ApiKey [API-KEY] to authorize. Currently using this key is equal to login in with username/password, but in the future we might like to be able to create restricted api keys that can only do certain features. An example would be an api key for a build bot that can only upload a certain package or only documentation for packages.

import Data.SafeCopy (base, deriveSafeCopy)
import Data.Typeable (Typeable)

newtype AuthToken = AuthToken T.Text
Copy link
Contributor

@dcoutts dcoutts Sep 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be Text? It's just base16 encoded bytes right?

I'd suggest we internally represent the token as the raw bytes (in a ShortByteString) and only convert to/from the base64 when rendering (e.g. in the ToJSON instance).

@dcoutts
Copy link
Contributor

dcoutts commented Sep 4, 2016

Great, this is looking good.

I'm not sure I get yet what the "token pair" is?

Also, is it standard to just have unadorned keys, or do we want a little bit of metadata attached (e.g. name/description) that people can use to help them keep track of which api key is used for what?

@agrafix
Copy link
Contributor Author

agrafix commented Sep 4, 2016

I've fixed all the review annotations and added the commits to the PR. The "token pair" is a token and a description :-)

@agrafix
Copy link
Contributor Author

agrafix commented Sep 4, 2016

And the build is green again and ready for (re)review

@agrafix
Copy link
Contributor Author

agrafix commented Sep 8, 2016

@dcoutts any news on this? :-)

@dcoutts
Copy link
Contributor

dcoutts commented Sep 10, 2016

Right, final review & merge, here we come...

nonceInPath dpath = maybe mzero return (Nonce . BS.pack <$> lookup "nonce" dpath)
nonceInPath dpath =
do raw <- maybe mzero return (lookup "nonce" dpath)
parseNonceM raw
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parseNonceM needs to be inside the maybe mzero return because parseNonceM returns fail, but we want mzero not fail. mzero will backtrack but fail will give a 5xx failure.

I can fix this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@dcoutts
Copy link
Contributor

dcoutts commented Sep 11, 2016

@agrafix So I'm changing the Authorisation header to use "X-ApiKey" rather than "ApiKey" since this is non-standard.

Now of course it'd be nice for people to know they can use this. Could you write up a short bit of documentation so that other people know how to use this auth method? Ie not just how to issue and revoke keys but also how to use the HTTP header.

@agrafix
Copy link
Contributor Author

agrafix commented Sep 11, 2016

@dcoutts okay for X-ApiKey.

About the docs: Where should I best put that? Add it to the user management page? Or is there some sort of help page?

@dcoutts
Copy link
Contributor

dcoutts commented Sep 11, 2016

About the docs: Where should I best put that? Add it to the user management page? Or is there some sort of help page?

Good idea, perhaps just document it directly on the tokens management page.

@dcoutts
Copy link
Contributor

dcoutts commented Sep 11, 2016

@agrafix I've made a number of changes and pushed it to a branch https://github.com/haskell/hackage-server/tree/auth-tokens

Now just testing I've not broken it all...

@agrafix
Copy link
Contributor Author

agrafix commented Sep 11, 2016

@dcoutts Does authTokensToCSV do proper escaping for the description of the tokens? Otherwise a , will break the CSV.

Should I add the docs to this PR or wait for the other branch to be ready and add it there?

@dcoutts
Copy link
Contributor

dcoutts commented Sep 11, 2016

@agrafix add it to the other branch.

@dcoutts
Copy link
Contributor

dcoutts commented Sep 11, 2016

Does authTokensToCSV do proper escaping for the description of the tokens? Otherwise a , will break the CSV.

Yes, e.g.

"0.1"
"uid","token","description"
"0","0f1cf740337c558bb93edd3e90f4445322e4dfc8599a8e55c72be9699978cbb7","blah"
"0","c5d315bc80ab185c309c6c169a6f9725761840522cd05142ec74772569887e6a","this and that, or the other"

@dcoutts dcoutts merged commit 2b29aa5 into haskell:master Sep 11, 2016
@dcoutts
Copy link
Contributor

dcoutts commented Sep 11, 2016

@agrafix ok, merged (and squashed since it reads better at the end in this case I think) so feel free to make a new PR against the master branch.

@agrafix agrafix mentioned this pull request Sep 11, 2016
@agrafix
Copy link
Contributor Author

agrafix commented Sep 11, 2016

@dcoutts okay, will do! Thanks :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants