Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

added jwt token auth middleware #916

Merged
merged 2 commits into from
Feb 25, 2018

Conversation

Shivakishore14
Copy link
Contributor

Added Basic JWT authentication middleware, resolves #399

@robbyoconnor
Copy link
Contributor

Following.

@markbates markbates added this to the 0.11.0 milestone Feb 14, 2018
Copy link
Member

@markbates markbates left a comment

Choose a reason for hiding this comment

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

Overall this looks great! My only real comments are we should accept an options struct that allows for setting the secret and the signing method, since not everyone uses HMAC. the default for those should be an env, like you have, and HMAC.

Other than that, this looks great!

ErrBadSigningMethod = errors.New("unexpected signing method")
)
// Middleware enables jwt token verification
func Middleware(next buffalo.Handler) buffalo.Handler {
Copy link
Member

Choose a reason for hiding this comment

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

Take an options struct that allows for setting the secret key and the signing method.

func Middleware(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
authString := c.Request().Header.Get("Authorization")
SecretKey := envy.Get("JWT_SECRET", "secret")
Copy link
Member

Choose a reason for hiding this comment

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

lower case secretKey

@arschles
Copy link
Contributor

I really, really want this but I'm late to the party (obviously). I'm currently writing my own middleware to do JWT auth. Please let me know if I can help contribute here to get this across the line

@markbates
Copy link
Member

@Shivakishore14 do you think you can make the requested changes in the next few days? If not, perhaps @arschles could make them. I'd love to get this in the next release.

@arschles
Copy link
Contributor

I can take a crack over the weekend or Monday. Let me know :)

@Shivakishore14
Copy link
Contributor Author

@arschles thanks for the offer, @markbates i am almost done with the code. I will be finishing up by tomorrow.
@arschles If you feel i missed something you can always contribute, again thanks for the offer :)

@markbates
Copy link
Member

Excellent! Lots of people are excited about this one.

@robbyoconnor
Copy link
Contributor

Do git pull --rebase and squash to one commit -- makes the PR easier to follow.

@robbyoconnor
Copy link
Contributor

@Shivakishore14 also update docs 😉

@arschles
Copy link
Contributor

@Shivakishore14 for sure. I'll look at this over the weekend. If there's more to do I'll do it in a follow-up. I don't want to hold up this PR

@Shivakishore14
Copy link
Contributor Author

@markbates can you review the code.

// helper function to get key for validation
// checks the algorithm used for signing and returns key according to the algorithm used.
// eg HMAC used a key string and RSA uses public key to validate
func (options Options) getKey() (interface{}, error) {
Copy link
Member

Choose a reason for hiding this comment

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

This all seems a bit much, and doesn't allow for users to add their own way of getting a key, such as from a database, or other store.

What do you think of doing something like this:

type Options struct {
	SignMethod jwt.SigningMethod
	GetKey     func(jwt.SigningMethod) (interface{}, error)
}

func GetHMACKey(jwt.SigningMethod) (interface{}, error) {
	key, err := envy.MustGet("JWT_SECRET")
	return []byte(key), err
}

func Middleware(options Options) buffalo.MiddlewareFunc {
	// set sign method to HMAC if not provided
	if options.SignMethod == nil {
		options.SignMethod = jwt.SigningMethodHS256
	}

	if options.GetKey == nil {
		options.GetKey = GetHMACKey
	}

	// ....
}

Then we can add a few "default" implementation functions, like the GetHMACKey example. Then people can easily plugin one of the default methods, and if none of them work for their situation, it's easy enough for the to add their own implementations.

Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wow that is neat, i will change the implementation.
instead of setting default GetKey to GetHMACKey , can we do something like.

if options.GetKey == nil {
	options.GetKey = selectGetKeyFunc(options.SignMethod)
}

so we get the GetKey method that is appropriate to the sign method.
and GetKey never uses the signing method so, it can be GetKey func() (interface{}, error)

@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
Copy link
Member

Choose a reason for hiding this comment

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

I'm assuming all the files in the data folder are used for testing, correct? If so, perhaps we should rename that folder to something like test_certs or something so that people don't get confused and want to use them in production, which would be bad.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure will do.

@Shivakishore14
Copy link
Contributor Author

Shivakishore14 commented Feb 20, 2018

@markbates I have added the requested changes.

// Options for the JWT middleware
type Options struct {
SignMethod jwt.SigningMethod
GetKey func()(interface{}, error)
Copy link
Member

Choose a reason for hiding this comment

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

This needs to take jwt.SigningMethod for those who want to build their own function, they might need that information.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@markbates added this.

@robbyoconnor
Copy link
Contributor

@Shivakishore14 do git pull --rebase and squash your changes.

@markbates markbates merged commit 3644437 into gobuffalo:development Feb 25, 2018
@markbates
Copy link
Member

Great work on this! Thank you so much!

@robbyoconnor
Copy link
Contributor

@Shivakishore14 You really need to update the docs ;)

@Shivakishore14
Copy link
Contributor Author

@robbyoconnor Where do you want the docs to be on gobuffalo.io or the source code ?

@robbyoconnor
Copy link
Contributor

robbyoconnor commented May 8, 2018

Here. I made a ticket to track this: #1056

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

Successfully merging this pull request may close these issues.

4 participants