Skip to content
/ oauth2w Public

A HTTP middleware that enables authorization via the OpenID Connect protocol

License

Notifications You must be signed in to change notification settings

i-core/oauth2w

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oauth2w

GoDoc Build Status codecov Go Report Card

oauth2w is a HTTP middleware that enables authorization via the OpenID Connect protocol.

Installation

go get github.com/i-core/oauth2w

How it works

  1. A client sends HTTP request that contains an OpenID Connect Access Token within the header Authorization.
  2. The middleware requests user claims using the userinfo's endpoint of OpenID Connect Provider.
  3. The middleware requests user roles using the interface oauth2w.RoleFinder.
  4. 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.

Usage

Simple

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
}

Logging

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))
    // ...
}

Accessing user data

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))
}

Usage with Ory Hydra and Werther

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))
    // ...
}

Contributing

Thanks for your interest in contributing to this project. Get started with our Contributing Guide.

License

The code in this project is licensed under MIT license.

About

A HTTP middleware that enables authorization via the OpenID Connect protocol

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages