oauth2w is a HTTP middleware that enables authorization via the OpenID Connect protocol.
go get github.com/i-core/oauth2w
- A client sends HTTP request that contains an OpenID Connect Access Token within the header
Authorization
. - The middleware requests user claims using the userinfo's endpoint of OpenID Connect Provider.
- The middleware requests user roles using the interface
oauth2w.RoleFinder
. - The middleware validates that the user has the required roles, and according to it, allows or not the HTTP request.
Note 1. Getting user roles is out of scope the library. You must provide an implementation of oauth2w.RoleFinder
that receives user claims and returns the user's roles.
Note 2. The middleware add the default role "_default" to each authenticated user. You can use it in order to transparently add an access to endpoints that each authenticated user must have an access for.
package main
import (
"fmt"
"net/http"
"os"
"github.com/i-core/oauth2w"
)
const oidcEndpoint = "https://openid-connect-provider.org"
func main() {
authw, err := oauth2w.New(oidcEndpoint, &RoleFinder{})
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
http.HandleFunc("/profile", authw([]string{"user"})(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Profile page")
}))
http.HandleFunc("/admin", authw([]string{"admin"})(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Admin page")
}))
fmt.Println(http.ListenAndServe(":8080", nil))
}
// RoleFinder finds user roles in the user's claims.
type RoleFinder struct {}
func (f *RoleFinder) FindRoles(claims map[string]interface{}) ([]string, error) {
roleClaim, ok := claims['roles']
if !ok {
return nil, nil
}
roles, ok := roleClaim.([]interface{})
!ok {
return nil, fmt.Errorf("invalid role claim \"roles\"")
}
var vv []string
for _, role := range roles {
s, ok := role.(string)
if !ok {
return nil, fmt.Errorf("invalid role claim \"roles\"")
}
vv = append(vv, s)
}
return vv, nil
}
package main
import (
"fmt"
"github.com/i-core/oauth2w"
)
const oidcEndpoint = "https://openid-connect-provider.org"
func main() {
logPrintFn := func(ctx context.Context) func(string, ...interface{}) {
return func(msg string, keysAndValues ...interface{}) {
params = append([]interface{}{"Info:", msg}, ...keysAndValues)
fmt.Println(params...)
}
}
logDebugFn := func(ctx context.Context) func(string, ...interface{}) {
return func(msg string, keysAndValues ...interface{}) {
params = append([]interface{}{"Debug:", msg}, ...keysAndValues)
fmt.Println(params...)
}
}
authw, err := oauth2w.New(oidcEndpoint, &RoleFinder{}, oauth2w.WithLogPrint(logPrintFn), oauth2w.WithLogDebug(logDebugFn))
// ...
}
package main
import (
"fmt"
"net/http"
"os"
"github.com/i-core/oauth2w"
)
const oidcEndpoint = "https://openid-connect-provider.org"
func main() {
authw, err := oauth2w.New(oidcEndpoint, &RoleFinder{})
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
http.HandleFunc("/profile", authw(func(w http.ResponseWriter, r *http.Request) {
user := oauth2w.FindUser(r.Context())
fmt.Printf("User %v\n", user)
}))
fmt.Println(http.ListenAndServe(":8080", nil))
}
When you use OpenID Connect Provider ORY Hydra with Identity Provider Werther you can use
an implementation of RoleFinder
from package github.com/i-core/oauth2w/werther
.
With the default role claim:
package main
import (
"github.com/i-core/oauth2w"
"github.com/i-core/oauth2w/werther"
)
const (
oidcEndpoint = "https://openid-connect-provider.org"
roleGroupID = "myapp"
)
func main() {
authw, err := oauth2w.New(oidcEndpoint, werther.NewRoleFinder(roleGroupID))
// ...
}
With a custom name of the role claim:
package main
import (
"github.com/i-core/oauth2w"
"github.com/i-core/oauth2w/werther"
)
const (
oidcEndpoint = "https://openid-connect-provider.org"
roleClaim = "http://my-company.org/claims/roles"
roleGroupID = "myapp"
)
func main() {
authw, err := oauth2w.New(oidcEndpoint, werther.NewRoleFinder(roleGroupID).WithRoleClaim(roleClaim))
// ...
}
Thanks for your interest in contributing to this project. Get started with our Contributing Guide.
The code in this project is licensed under MIT license.