JWT Security
This package contains functions and types for enabling JWT as a security mechanism
in a microservice.
It integrates with Goa generated JWT security and also as part of the SecurityChain.
Setting up a JWT security
There are a couple of things you need to do to enable the JWT security middleware.
For details on JWT you can find many resources on the official site: http://jwt.io.
JWT has two main parts: issuing JWT tokens (with claims) and verifying the tokens.
This package provides means of validating a JWT token with claims by using secret
keys (RSA key pairs).
Setting up the secret keys
Create a directory in which you'll keep your key-pair:
mkdir rsa-keys
cd rsa-keys
The generate 2048-bit RSA key pair:
openssl genrsa -des3 -out private.pem 2048
The output the keys in PEM form:
openssl rsa -in private.pem -outform PEM -pubout -out public.pub
NOTE: Make sure that the public key ends in .pub
. This is how the default
key resolver of the library locates the public keys.
Set up JWT with Goagen
To use the JWT security you need to set up JWT security in your microservice Goa DSL.
In your design file, add the JWT setup:
var JWTAuth = JWTSecurity("JWT", func() {
Header("Authorization")
Scope("api:read", "Read access to the API")
Scope("api:write", "Write access to the API")
})
var _ = Resource("user", func() {
BasePath("/user")
// Other specification here ...
Security(JWTAuth) // Add the JWTAuth to this resource
})
By running goagen ...
on the deisgn again, you'll notice that Goa will
add a security file app/security.go
.
More details on how to configure the JWT security are available on the official
documentation:
The most important thing there is the security specification scheme - the following
function that builds JWTSecurity
:
// NewJWTSecurity creates a JWT security definition.
func NewJWTSecurity() *goa.JWTSecurity {
def := goa.JWTSecurity{
In: goa.LocHeader,
Name: "Authorization",
TokenURL: "",
Scopes: map[string]string{
"api:read": "Read access to the API",
"api:write": "Write access to the API",
},
}
return &def
}
We'll use this in the next step.
Setting up a SecurityChain
Once the security specs are generated by Goa, you need to set up a security chain
for the microservice.
In the main.go
file of your microservice, set up the JWT Security Chain
middleware and add it to the security chain.
import (
// other imports
"githib.com/Microkubes/microservice-security/auth"
"githib.com/Microkubes/microservice-security/chain"
"githib.com/Microkubes/microservice-security/jwt"
)
func main(){
// "secret-keys" is the directory containing the RSA keys
// app.NewJWTSecurity() creates the JWTSecurity scheme structure
JWTMiddleware := jwt.NewJWTSecurity("secret-keys", app.NewJWTSecurity())
sc := chain.NewSecurityChain(). // create new chain
AddMiddleware(JWTMiddleware). // Add the JWT middleware
AddMiddleware(chain.CheckAuthMiddleware) // add the check for authentication
// other initializations here...
service.Use(chain.ToGoaMiddleware(sc)) // attach the security chain as Goa middleware
}
Testing the setup
To test the setup, you'll need to generate and sign a JWT token, then use it in
the request header.
To generate a JWT, you can use different tools. In this example we'll use jwtgen
command line tool. To install it:
npm install -g jwtgen
Then, to generate the JWT token, type:
jwtgen -a RS256\
-p secret-keys/private.pem\
-c "userId=9479e3b6-a4c5-445c-aefe-c84b5a47ed3c" \
-c "username=test-user"\
-c "roles=user,admin"\
-c "organizations=Org1,Org2"
which will output the JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE1MDIyOTA3NDYsInVzZXJJZCI6Ijk0Nzl
lM2I2LWE0YzUtNDQ1Yy1hZWZlLWM4NGI1YTQ3ZWQzYyIsInVzZXJuYW1lIjoidGVzdC11c2VyIiwicm9
sZXMiOiJ1c2VyLGFkbWluIiwib3JnYW5pemF0aW9ucyI6Ik9yZzEsT3JnMiJ9.J2dFSUChwAyy3g92qj
6ggT-EA_B-kv16cjyEQS0xBTHl6Sw3vhsaooRTnFDkXKVeGqnctyjRLGmRxpQCYZ5FVnJocSCKw99Q1k
mr-HbyoLjjpppYOSC_LOyPPqmUe1M9ze5GOP_QY9H5V6g6Otar_Ge4tXoR9P7_px7KtHJ2jINeX_amxW
MnujN5fqsrI80wNSGcGTKwU2FSJynQoS_7zziHmCK0h1m-XV_wjaMu4h-_nHsK5pNAF1R7uWx20aAsg4
38wVjwdMmgDhRJOlctLwhFlthAr_GXYKDH-ztKGz6KNXRfUK8--ad4TaNgCDzbjVkHrgMLS-RatUXXoW
4pfw
(Note that the JWT is actually one line. For readability purposes it is displayed here
in multiple lines.)
Then you'll need to add the token in the Authorization
HTTP header of the request.
curl --header "Authorization: Bearer eyJ0eXAiOiJKV1Q...<full token here>...4pfw" "http://localhost:8080/user/1"