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

Feature/implement backend authentication #68

Merged
merged 20 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7618acd
feat: created authenticator
Zheng-Zhi-Qiang Feb 18, 2024
e37a5e8
feat: added middleware to authenticate user
Zheng-Zhi-Qiang Feb 18, 2024
8431734
Merge branch 'main' into feature/implement-backend-authentication
Zheng-Zhi-Qiang Feb 25, 2024
493fd96
refactor: updated handler error according to PR#68
Zheng-Zhi-Qiang Feb 25, 2024
ada7e13
refactor: removed session store implementation for authentication
Zheng-Zhi-Qiang Feb 25, 2024
e0b956f
Merge branch 'main' into feature/implement-backend-authentication
Zheng-Zhi-Qiang Feb 25, 2024
946605b
refactor: moved auth middleware to middleware.go under server package…
Zheng-Zhi-Qiang Feb 25, 2024
c5100ed
fix: added auth middleware to server instantiation
Zheng-Zhi-Qiang Feb 25, 2024
87d36b7
fix: added string parsing to get access token from bearer token
Zheng-Zhi-Qiang Feb 25, 2024
9adb4ab
fix: added missing logging to auth middleware
Zheng-Zhi-Qiang Feb 25, 2024
7f087b3
refactor: changed to auth functions for backend api instead of applic…
Zheng-Zhi-Qiang Mar 1, 2024
f31b28e
fix: changed healthcheck message sent to string instead of bytes as e…
Zheng-Zhi-Qiang Mar 1, 2024
e490f66
refactor: applied respective authentication function to routes
Zheng-Zhi-Qiang Mar 3, 2024
2afbff7
refactor: removed env_file setting from docker compose and specified …
Zheng-Zhi-Qiang Mar 3, 2024
a56bd7f
refactor: removed uneccessary logging from auth functions
Zheng-Zhi-Qiang Mar 3, 2024
59bd685
refactor: reduced authorization functions to only one to differentiat…
Zheng-Zhi-Qiang Mar 7, 2024
bd45275
fix: restricted pipeline resources to admins and unrestricted healthc…
Zheng-Zhi-Qiang Mar 7, 2024
cdac4e5
fix: merge conflict in compose.yaml
Zheng-Zhi-Qiang Mar 7, 2024
4ec3b0f
fix: resolved merged conflicts
Zheng-Zhi-Qiang Mar 7, 2024
c396393
refactor: moved permission check function from helper to middleware
Zheng-Zhi-Qiang Mar 8, 2024
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
13 changes: 11 additions & 2 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,25 @@ require (
go.mongodb.org/mongo-driver v1.13.1
)

require github.com/gorilla/securecookie v1.1.2 // indirect

require (
github.com/coreos/go-oidc/v3 v3.9.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/gorilla/sessions v1.2.2
github.com/klauspost/compress v1.13.6 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
34 changes: 34 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4=
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=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA=
github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
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.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gookit/event v1.1.1 h1:heYaXz4N2/0bgvGIwpEEfdW3PAaSWesGHy9/C+ZnZRI=
github.com/gookit/event v1.1.1/go.mod h1:n0XbUJ4kqoCwhLOMeyyitM1AKa+dPgUPuy1vSybHXjg=
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
Expand All @@ -20,6 +35,8 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6f
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
Expand All @@ -34,18 +51,25 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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-20190412213103-97732733099d/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=
Expand All @@ -60,11 +84,21 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
52 changes: 52 additions & 0 deletions backend/src/authenticator/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package authenticator

import (
"context"
"errors"
"os"

"github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2"
)

// Authenticator is used to authenticate our users.
type Authenticator struct {
*oidc.Provider
oauth2.Config
}

func New() (*Authenticator, error) {
provider, err := oidc.NewProvider(
context.Background(),
"https://"+os.Getenv("AUTH0_DOMAIN")+"/",
)
if err != nil {
return nil, err
}

conf := oauth2.Config{
ClientID: os.Getenv("AUTH0_CLIENT_ID"),
ClientSecret: os.Getenv("AUTH0_CLIENT_SECRET"),
RedirectURL: os.Getenv("AUTH0_CALLBACK_URL"),
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID, "profile"},
Copy link
Owner

Choose a reason for hiding this comment

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

should we be setting the scope here? I'm not too familiar

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was based off their quick start guide so we just stick with this first until changes are required bah since it doesn't seem to create any immediate issues in my mind

}

return &Authenticator{
Provider: provider,
Config: conf,
}, nil
}

func (a *Authenticator) VerifyIDToken(ctx context.Context, token *oauth2.Token) (*oidc.IDToken, error) {
rawIDToken, ok := token.Extra("id_token").(string)
Copy link
Owner

Choose a reason for hiding this comment

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

what is this Extra("id_token") about actually? Can you provide a reference/documentation for me to take a look at the id_token field that is present in oauth2 JWT?

Copy link
Owner

Choose a reason for hiding this comment

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

Also, I just read up more on the different token types for JWT. There is an ID token and Access token type. ID tokens should be used for authentication (i.e. a user is a valid user) and access tokens should be used for authorisation (i.e. a user is valid and is authorised to perform a certain action).

from https://auth0.com/docs/secure/tokens/id-tokens: ID Tokens should never be used to obtain direct access to APIs or to make authorization decisions.

So you'll need to consider which APIs require an ID token, and which ones require an Access token and use the correct middleware accordingly. In our scenario, I believe we should be using Access tokens instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The quick start guide I was using is post login when I created the application. The guide only showed how to integrate authentication and not authorisation, hence the discrepancy here I think. Ill just refer to the guide you mentioned.

if !ok {
return nil, errors.New("no id_token field in oauth2 token")
}

oidcConfig := &oidc.Config{
ClientID: a.ClientID,
}

return a.Verifier(oidcConfig).Verify(ctx, rawIDToken)
}
3 changes: 3 additions & 0 deletions backend/src/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/gorilla/mux"
"github.com/joshtyf/flowforge/src/api"
"github.com/joshtyf/flowforge/src/execute"
"github.com/joshtyf/flowforge/src/middleware"
)

func main() {
Expand All @@ -17,6 +18,8 @@ func main() {
srm.Start()

r := mux.NewRouter()
r.Use(middleware.IsAuthenticated)

r.HandleFunc("/api/healthcheck", api.NewHandler(api.HealthCheck)).Methods("GET")
r.HandleFunc("/api/service_request", api.NewHandler(api.CreateServiceRequest)).Methods("POST").Headers("Content-Type", "application/json")
r.HandleFunc("/api/service_request/{requestId}", api.NewHandler(api.GetServiceRequest)).Methods("GET")
Expand Down
82 changes: 82 additions & 0 deletions backend/src/middleware/auth_middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package middleware

import (
"encoding/json"
"errors"
"net/http"
"os"

"github.com/gorilla/sessions"

"github.com/joshtyf/flowforge/src/api"
"github.com/joshtyf/flowforge/src/authenticator"
"github.com/joshtyf/flowforge/src/logger"
"golang.org/x/oauth2"
)

var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY")))

func IsAuthenticated(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
accessToken := r.Header.Get("Authorization")
session, _ := store.Get(r, accessToken)
Copy link
Owner

@joshtyf joshtyf Feb 21, 2024

Choose a reason for hiding this comment

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

typically, the value in this header will be Bearer <token>. For example, using auth0, typically the frontend will get the token of type Bearer. They will then form the Bearer <token> string and pass it to the backend. You can see it from the React example provided directly from Auth0 https://auth0.com/docs/quickstart/spa/react/02-calling-an-api

So you will probably need to do some string parsing to get the token from the Authorization header.


var profile map[string]interface{}
profile, ok := session.Values["profile"].(map[string]interface{})

if ok {
logger.Info("[Authorization] Previously authorised", nil)
next.ServeHTTP(w, r)
}

authToken := &oauth2.Token{AccessToken: accessToken}
if accessToken == "" {
authError := &api.HandlerError{Error: errors.New("authorization token missing"), Code: http.StatusUnauthorized}
w.WriteHeader(authError.Code)
json.NewEncoder(w).Encode(authError)
return
}

auth, err := authenticator.New()
if err != nil {
logger.Error("[Authorization] Failed to initialize authenticator", map[string]interface{}{"err": err})
authError := &api.HandlerError{Error: api.ErrInternalServerError, Code: http.StatusInternalServerError}
w.WriteHeader(authError.Code)
json.NewEncoder(w).Encode(authError)
return
}

idToken, err := auth.VerifyIDToken(r.Context(), authToken)
if err != nil {
logger.Error("[Authorization] Unable to verify token", map[string]interface{}{"err": err})
authError := &api.HandlerError{Error: errors.New("unable to verify token"), Code: http.StatusUnauthorized}
w.WriteHeader(authError.Code)
json.NewEncoder(w).Encode(authError)
Copy link
Owner

Choose a reason for hiding this comment

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

encoding the error like this will not work. see my PR #65 description (or see this stack overflow answer https://stackoverflow.com/questions/44989924/golang-error-types-are-empty-when-encoded-to-json)

return
}

err = idToken.Claims(&profile)
if err != nil {
logger.Error("[Authorization] Unable retrieve profile", map[string]interface{}{"err": err})
authError := &api.HandlerError{Error: errors.New("unable to retrieve profile"), Code: http.StatusInternalServerError}
w.WriteHeader(authError.Code)
json.NewEncoder(w).Encode(authError)
return
}

session.Values["access_token"] = authToken.AccessToken
session.Values["profile"] = profile
err = session.Save(r, w)
if err != nil {
logger.Error("[Authorization] Unable save session", map[string]interface{}{"err": err})
authError := &api.HandlerError{Error: errors.New("unable to save session"), Code: http.StatusInternalServerError}
w.WriteHeader(authError.Code)
json.NewEncoder(w).Encode(authError)
return
}

// Call the next middleware function or final handler
next.ServeHTTP(w, r)
})
}
Loading