Skip to content
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

Implemented Authentication Middelware #21

Merged
merged 28 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fe8ca44
implemented add token for queue store
aneeshsharma Feb 12, 2022
823cefe
implemented create token route
aneeshsharma Feb 12, 2022
42120c2
Fix code style issues with gofmt
lint-action Feb 12, 2022
4ec0ec9
read tokens in the queue in readqueue
aneeshsharma Feb 14, 2022
9f4467e
Merge branch 'add-token' of github.com:SimplQ/simplQ-golang into add-…
aneeshsharma Feb 14, 2022
a44aee0
Fix code style issues with gofmt
lint-action Feb 14, 2022
d477b23
implemented token number
aneeshsharma Feb 26, 2022
c7875b4
merged origin add-token
aneeshsharma Feb 26, 2022
5299a8e
Fix code style issues with gofmt
lint-action Feb 26, 2022
085b8bd
added read token route
aneeshsharma Feb 26, 2022
310e9fb
Merge branch 'add-token' of github.com:SimplQ/simplQ-golang into add-…
aneeshsharma Feb 26, 2022
16e8417
Fix code style issues with gofmt
lint-action Feb 26, 2022
534fd6a
separated name length constants
aneeshsharma Feb 26, 2022
36a4f77
Merge branch 'add-token' of github.com:SimplQ/simplQ-golang into add-…
aneeshsharma Feb 26, 2022
4bc6002
log insert error for add token
aneeshsharma Mar 2, 2022
8533b6c
Fix code style issues with gofmt
lint-action Mar 2, 2022
5197343
implemented authentication token middleware
aneeshsharma Mar 5, 2022
dbc72e5
Fix code style issues with gofmt
lint-action Mar 5, 2022
beeae61
explaning comments
aneeshsharma Mar 11, 2022
6b9bfb4
Fix code style issues with gofmt
lint-action Mar 11, 2022
de112cf
Update authorization with main (#20)
aneeshsharma Mar 12, 2022
5f022f8
Merge branch 'main' into authorization
aneeshsharma Mar 12, 2022
8db5c18
use 'uid' as a constant
aneeshsharma Mar 19, 2022
d031da7
Merge branch 'authorization' of github.com:SimplQ/simplQ-golang into …
aneeshsharma Mar 19, 2022
5f24ab8
renamed common.go to middleware.go for authentication package
aneeshsharma Mar 19, 2022
f6345bf
Fix code style issues with gofmt
lint-action Mar 19, 2022
4cd7791
made getJWTValidator private
aneeshsharma Mar 19, 2022
27032cb
Merge branch 'authorization' of github.com:SimplQ/simplQ-golang into …
aneeshsharma Mar 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ build/
# temporary build files create by air
tmp/

# dotenv variables
# env file
.env
Copy link
Contributor

Choose a reason for hiding this comment

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

Why should this be gitignored?

If it's okay, let's checkin the default .env file, it will be easier for others to run the code my making minimal edits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It shouldn't be a problem right now. But since we also store secrets as env variables, I just added it to gitignore. Also, I think generally most projects keep .env in .gitignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it would be better to store these values as constants inside a go file instead of committing the .env file to git.

6 changes: 6 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import (
"os"

"github.com/SimplQ/simplQ-golang/internal/mux"

"github.com/joho/godotenv"
)

func main() {
// Load environment variables if .env file is present
// ignore if not present
godotenv.Load()

routes := mux.InitalizeRoutes()

listenAddr := ":8080"
Expand Down
11 changes: 7 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ require (
go.mongodb.org/mongo-driver v1.8.1
)

require gopkg.in/square/go-jose.v2 v2.6.0 // indirect

require (
github.com/auth0/go-jwt-middleware/v2 v2.0.0
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/joho/godotenv v1.4.0
github.com/klauspost/compress v1.13.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
github.com/ttacon/libphonenumber v1.2.1 // indirect
github.com/ttacon/libphonenumber v1.2.1
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.0.2 // indirect
github.com/xdg-go/stringprep v1.0.2 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f // indirect
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
golang.org/x/text v0.3.5 // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/protobuf v1.26.0 // indirect
)
23 changes: 19 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/auth0/go-jwt-middleware/v2 v2.0.0 h1:jft2yYteA6wpwTj1uxSLwE0TlHCjodMQvX7+eyqJiOQ=
github.com/auth0/go-jwt-middleware/v2 v2.0.0/go.mod h1:/y7nPmfWDnJhCbFq22haCAU7vufwsOUzTthLVleE6/8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -11,8 +13,11 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand All @@ -24,8 +29,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 h1:5u+EJUQiosu3JFX0XS0qTf5FznsMOzTjGqavBGuCbo0=
Expand All @@ -43,19 +49,26 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7Jul
go.mongodb.org/mongo-driver v1.8.1 h1:OZE4Wni/SJlrcmSIBRYNzunX5TKxjrTS4jKSnA99oKU=
go.mongodb.org/mongo-driver v1.8.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f h1:aZp0e2vLN4MToVqnjNEYEtrEA8RH8U8FN1CU7JgqsPU=
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
Expand All @@ -65,5 +78,7 @@ google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/l
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
118 changes: 118 additions & 0 deletions internal/authentication/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package authentication

import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"os"
"strings"
"time"

"github.com/auth0/go-jwt-middleware/v2/jwks"
"github.com/auth0/go-jwt-middleware/v2/validator"
)

// Prefix of the authorization header for an anonymous user
const ANONYMOUS_PREFIX = "Anonymous"

// Prefix of the authorization header for an authenticated user
const BEARER_PREFIX = "Bearer"

// Key for the "uid" stored in context
const UID = "uid"

// Authentication Middleware
// Calls the next handler with `uid` in the `context` which can be used as a unique
// id for any user.
// Returns `http.StatusUnauthorized` to the client if the authorization token is not
// found or is invalid.
func AuthMiddleware(next http.Handler) http.Handler {
tokenValidator := getJWTValidator()

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authorization_header := r.Header.Get("Authorization")

// Default error message
errorMessage := "Invalid authorization"

if strings.HasPrefix(authorization_header, ANONYMOUS_PREFIX) {
// For anonymous authentication

// Get the token from the header
uid := strings.Split(authorization_header, ANONYMOUS_PREFIX)[1]
uid = strings.Trim(uid, " \n\r")

// If a valid token is present
if len(uid) > 0 {
// Add given token as uid to the context
ctx := context.WithValue(r.Context(), UID, uid)
next.ServeHTTP(w, r.WithContext(ctx))
return
}

errorMessage = "Anonymous token not found"
} else if strings.HasPrefix(authorization_header, BEARER_PREFIX) {
// For bearer authentication

// Get the JWT token from the header
token := strings.Split(authorization_header, BEARER_PREFIX)[1]
token = strings.Trim(token, " \n\r")

// if a token is present
if len(token) > 0 {
// Validate the JWT token and get claims
tokenDecoded, err := tokenValidator.ValidateToken(context.TODO(), token)

if err == nil {
tokenDecoded := tokenDecoded.(*validator.ValidatedClaims)

// Use the "sub" claim as the uid
uid := tokenDecoded.RegisteredClaims.Subject

// if a valid uid is present
if len(uid) > 0 {
// Add the given "sub" as the uid to the context
ctx := context.WithValue(r.Context(), UID, uid)
next.ServeHTTP(w, r.WithContext(ctx))
return
}
} else {
log.Println(err)
}
}
errorMessage = "Invalid authentication token"
}

// If the next handler wasn't called, authentication failed
// return Unauthorized http error
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(fmt.Sprintf(`{"message": "%s"}`, errorMessage)))
})
}

// Returns a JWT Token validator
func getJWTValidator() *validator.Validator {
issuerURL, err := url.Parse("https://" + os.Getenv("AUTH0_DOMAIN") + "/")
if err != nil {
log.Fatalf("Failed to parse the issuer url: %v", err)
}

provider := jwks.NewCachingProvider(issuerURL, 5*time.Minute)

jwtValidator, err := validator.New(
provider.KeyFunc,
validator.RS256,
issuerURL.String(),
[]string{os.Getenv("AUTH0_AUDIENCE")},
validator.WithAllowedClockSkew(time.Minute),
)

if err != nil {
log.Fatalf("Failed to set up the jwt validator")
}

return jwtValidator
}
7 changes: 7 additions & 0 deletions internal/handler/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"time"

"github.com/SimplQ/simplQ-golang/internal/authentication"
"github.com/SimplQ/simplQ-golang/internal/datastore"
"github.com/SimplQ/simplQ-golang/internal/models/api"
"github.com/SimplQ/simplQ-golang/internal/models/db"
Expand All @@ -20,11 +21,17 @@ const queueId key = 0

func GetQueue(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(queueId).(string)
uid := r.Context().Value(authentication.UID).(string)
// TODO: Remove print statement once uid is made use of
log.Println(uid)
aneeshsharma marked this conversation as resolved.
Show resolved Hide resolved

if id == "" {
http.Error(w, fmt.Sprintf("Invalid Id: %s", id), http.StatusBadRequest)
return
}

queue, err := datastore.Store.ReadQueue(db.QueueId(id))

if err != nil {
http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
return
Expand Down
5 changes: 5 additions & 0 deletions internal/mux/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"

"github.com/SimplQ/simplQ-golang/internal/authentication"
"github.com/SimplQ/simplQ-golang/internal/handler"
)

Expand All @@ -21,6 +22,8 @@ func InitalizeRoutes() chi.Router {

// Routes for "queue" resource
r.Route("/queue", func(r chi.Router) {
// all routes under queue are required to have authentication
r.Use(authentication.AuthMiddleware)
// POST /articles
r.Post("/", handler.CreateQueue)

Expand All @@ -36,6 +39,8 @@ func InitalizeRoutes() chi.Router {

// Routes for "token" resource
r.Route("/token", func(r chi.Router) {
// all routes under token are required to have authentication
r.Use(authentication.AuthMiddleware)
// Add new token to queue
r.Post("/", handler.CreateToken)

Expand Down