OpenID Connect (oidc) support
OpenID Connect seems like an easier way to offer login than oauth2.
If you think that this is a good idea, I could try to add it as a subpackage github.com/volatiletech/authboss/v3/oauth2/oidc.
Here is my current implementation (based on https://github.com/caos/oidc):
package oidc
import (
"context"
"fmt"
"net/http"
"time"
"github.com/caos/oidc/pkg/client"
httphelper "github.com/caos/oidc/pkg/http"
caosoidc "github.com/caos/oidc/pkg/oidc"
"github.com/volatiletech/authboss/v3"
aboauth2 "github.com/volatiletech/authboss/v3/oauth2"
"golang.org/x/oauth2"
)
// NewProvider discovers the configuration of the OpenID Connect provider, based on issuer.
func NewProvider(issuer, clientID, clientSecret string, scopes []string) (authboss.OAuth2Provider, error) {
cfg := &oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
RedirectURL: "", // will be filled later during init
Scopes: scopes,
}
httpClient := &http.Client{
Timeout: 30 * time.Second,
}
dicovered, err := client.Discover(issuer, httpClient)
if err != nil {
return authboss.OAuth2Provider{}, err
}
cfg.Endpoint = oauth2.Endpoint{
AuthURL: dicovered.AuthorizationEndpoint,
TokenURL: dicovered.TokenEndpoint,
}
return authboss.OAuth2Provider{
OAuth2Config: cfg,
FindUserDetails: func(ctx context.Context, cfg oauth2.Config, token *oauth2.Token) (map[string]string, error) {
req, err := http.NewRequest("GET", dicovered.UserinfoEndpoint, nil)
if err != nil {
return nil, err
}
req.Header.Set("authorization", token.TokenType+" "+token.AccessToken)
userinfo := caosoidc.NewUserInfo()
if err := httphelper.HttpRequest(httpClient, req, &userinfo); err != nil {
return nil, err
}
user := map[string]string{
aboauth2.OAuth2UID: userinfo.GetSubject(),
}
if email := userinfo.GetEmail(); email != "" {
user[aboauth2.OAuth2Email] = email
}
return user, nil
},
}, nil
}
If you want to champion this then I'm all for it. Just improves Authboss in general so I think that's great. I don't have any experience with OpenID Connect but it does seem quite popular.
I have created an external module to experiment on this: https://pkg.go.dev/git.sr.ht/~oliverpool/goath
It seems to work fine in my case, but I would really appreciate a review!
import "git.sr.ht/~oliverpool/goath/goauthboss"
// ...
ab = authboss.New()
goauthboss.Init(ab, map[string]goath.Provider{
"oidc": &coreos.OIDC{...},
}, store)
In there, I also did the cleanup that I suggested here: https://github.com/volatiletech/authboss/issues/333#issuecomment-1034989236