Skip to content

Commit

Permalink
Merge pull request #56 from caos/service-accounts
Browse files Browse the repository at this point in the history
feat: jwt profile grant
  • Loading branch information
hifabienne committed Sep 16, 2020
2 parents 30f60da + c90a9d5 commit e96815f
Show file tree
Hide file tree
Showing 44 changed files with 2,241 additions and 1,462 deletions.
58 changes: 25 additions & 33 deletions example/client/app/app.go
Expand Up @@ -6,10 +6,10 @@ import (
"fmt"
"net/http"
"os"

"github.com/sirupsen/logrus"
"time"

"github.com/google/uuid"
"github.com/sirupsen/logrus"

"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/pkg/rp"
Expand All @@ -29,41 +29,30 @@ func main() {

ctx := context.Background()

rpConfig := &rp.Config{
ClientID: clientID,
ClientSecret: clientSecret,
Issuer: issuer,
CallbackURL: fmt.Sprintf("http://localhost:%v%v", port, callbackPath),
Scopes: []string{"openid", "profile", "email"},
}
redirectURI := fmt.Sprintf("http://localhost:%v%v", port, callbackPath)
scopes := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail}
cookieHandler := utils.NewCookieHandler(key, key, utils.WithUnsecure())
provider, err := rp.NewDefaultRP(rpConfig, rp.WithCookieHandler(cookieHandler)) //rp.WithPKCE(cookieHandler)) //,
provider, err := rp.NewRelayingPartyOIDC(issuer, clientID, clientSecret, redirectURI, scopes,
rp.WithPKCE(cookieHandler),
rp.WithVerifierOpts(rp.WithIssuedAtOffset(5*time.Second)),
)
if err != nil {
logrus.Fatalf("error creating provider %s", err.Error())
}

// state := "foobar"
state := uuid.New().String()

http.Handle("/login", provider.AuthURLHandler(state))
// http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
// http.Redirect(w, r, provider.AuthURL(state), http.StatusFound)
// })
//generate some state (representing the state of the user in your application,
//e.g. the page where he was before sending him to login
state := func() string {
return uuid.New().String()
}

// http.HandleFunc(callbackPath, func(w http.ResponseWriter, r *http.Request) {
// tokens, err := provider.CodeExchange(ctx, r.URL.Query().Get("code"))
// if err != nil {
// http.Error(w, "failed to exchange token: "+err.Error(), http.StatusUnauthorized)
// return
// }
// data, err := json.Marshal(tokens)
// if err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// return
// }
// w.Write(data)
// })
//register the AuthURLHandler at your preferred path
//the AuthURLHandler creates the auth request and redirects the user to the auth server
//including state handling with secure cookie and the possibility to use PKCE
http.Handle("/login", rp.AuthURLHandler(state, provider))

//for demonstration purposes the returned tokens (access token, id_token an its parsed claims)
//are written as JSON objects onto response
marshal := func(w http.ResponseWriter, r *http.Request, tokens *oidc.Tokens, state string) {
_ = state
data, err := json.Marshal(tokens)
Expand All @@ -74,10 +63,13 @@ func main() {
w.Write(data)
}

http.Handle(callbackPath, provider.CodeExchangeHandler(marshal))
//register the CodeExchangeHandler at the callbackPath
//the CodeExchangeHandler handles the auth response, creates the token request and calls the callback function
//with the returned tokens from the token endpoint
http.Handle(callbackPath, rp.CodeExchangeHandler(marshal, provider))

http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
tokens, err := provider.ClientCredentials(ctx, "scope")
tokens, err := rp.ClientCredentials(ctx, provider, "scope")
if err != nil {
http.Error(w, "failed to exchange token: "+err.Error(), http.StatusUnauthorized)
return
Expand All @@ -92,5 +84,5 @@ func main() {
})
lis := fmt.Sprintf("127.0.0.1:%s", port)
logrus.Infof("listening on http://%s/", lis)
logrus.Fatal(http.ListenAndServe("127.0.0.1:5556", nil))
logrus.Fatal(http.ListenAndServe("127.0.0.1:"+port, nil))
}
41 changes: 27 additions & 14 deletions example/client/github/github.go
Expand Up @@ -3,11 +3,16 @@ package main
import (
"context"
"fmt"
"github.com/caos/oidc/pkg/cli"
"github.com/caos/oidc/pkg/rp"
"os"

"github.com/google/go-github/v31/github"
"github.com/google/uuid"
"golang.org/x/oauth2"
githubOAuth "golang.org/x/oauth2/github"
"os"

"github.com/caos/oidc/pkg/rp"
"github.com/caos/oidc/pkg/rp/cli"
"github.com/caos/oidc/pkg/utils"
)

var (
Expand All @@ -20,24 +25,32 @@ func main() {
clientSecret := os.Getenv("CLIENT_SECRET")
port := os.Getenv("PORT")

rpConfig := &rp.Config{
rpConfig := &oauth2.Config{
ClientID: clientID,
ClientSecret: clientSecret,
CallbackURL: fmt.Sprintf("http://localhost:%v%v", port, callbackPath),
RedirectURL: fmt.Sprintf("http://localhost:%v%v", port, callbackPath),
Scopes: []string{"repo", "repo_deployment"},
Endpoints: githubOAuth.Endpoint,
Endpoint: githubOAuth.Endpoint,
}

oauth2Client := cli.CodeFlowForClient(rpConfig, key, callbackPath, port)

client := github.NewClient(oauth2Client)

ctx := context.Background()
_, _, err := client.Users.Get(ctx, "")
cookieHandler := utils.NewCookieHandler(key, key, utils.WithUnsecure())
relayingParty, err := rp.NewRelayingPartyOAuth(rpConfig, rp.WithCookieHandler(cookieHandler))
if err != nil {
fmt.Println("OAuth flow failed")
} else {
fmt.Printf("error creating relaying party: %v", err)
return
}
state := func() string {
return uuid.New().String()
}
token := cli.CodeFlow(relayingParty, callbackPath, port, state)

client := github.NewClient(relayingParty.Client(ctx, token.Token))

fmt.Println("OAuth flow success")
_, _, err = client.Users.Get(ctx, "")
if err != nil {
fmt.Printf("error %v", err)
return
}
fmt.Println("call succeeded")
}
14 changes: 11 additions & 3 deletions example/internal/mock/storage.go
Expand Up @@ -151,8 +151,8 @@ func (s *AuthStorage) AuthRequestByID(_ context.Context, id string) (op.AuthRequ
}
return a, nil
}
func (s *AuthStorage) CreateToken(_ context.Context, authReq op.AuthRequest) (string, time.Time, error) {
return authReq.GetID(), time.Now().UTC().Add(5 * time.Minute), nil
func (s *AuthStorage) CreateToken(_ context.Context, authReq op.TokenRequest) (string, time.Time, error) {
return "id", time.Now().UTC().Add(5 * time.Minute), nil
}
func (s *AuthStorage) TerminateSession(_ context.Context, userID, clientID string) error {
return nil
Expand All @@ -174,6 +174,10 @@ func (s *AuthStorage) GetKeySet(_ context.Context) (*jose.JSONWebKeySet, error)
},
}, nil
}
func (s *AuthStorage) GetKeyByIDAndUserID(_ context.Context, _, _ string) (*jose.JSONWebKey, error) {
pubkey := s.key.Public()
return &jose.JSONWebKey{Key: pubkey, Use: "sig", Algorithm: "RS256", KeyID: "1"}, nil
}

func (s *AuthStorage) GetClientByClientID(_ context.Context, id string) (op.Client, error) {
if id == "none" {
Expand All @@ -182,20 +186,24 @@ func (s *AuthStorage) GetClientByClientID(_ context.Context, id string) (op.Clie
var appType op.ApplicationType
var authMethod op.AuthMethod
var accessTokenType op.AccessTokenType
var responseTypes []oidc.ResponseType
if id == "web" {
appType = op.ApplicationTypeWeb
authMethod = op.AuthMethodBasic
accessTokenType = op.AccessTokenTypeBearer
responseTypes = []oidc.ResponseType{oidc.ResponseTypeCode}
} else if id == "native" {
appType = op.ApplicationTypeNative
authMethod = op.AuthMethodNone
accessTokenType = op.AccessTokenTypeBearer
responseTypes = []oidc.ResponseType{oidc.ResponseTypeCode}
} else {
appType = op.ApplicationTypeUserAgent
authMethod = op.AuthMethodNone
accessTokenType = op.AccessTokenTypeJWT
responseTypes = []oidc.ResponseType{oidc.ResponseTypeIDToken, oidc.ResponseTypeIDTokenOnly}
}
return &ConfClient{ID: id, applicationType: appType, authMethod: authMethod, accessTokenType: accessTokenType, devMode: false}, nil
return &ConfClient{ID: id, applicationType: appType, authMethod: authMethod, accessTokenType: accessTokenType, responseTypes: responseTypes, devMode: false}, nil
}

func (s *AuthStorage) AuthorizeClientIDSecret(_ context.Context, id string, _ string) error {
Expand Down
2 changes: 1 addition & 1 deletion example/server/default/default.go
Expand Up @@ -21,7 +21,7 @@ func main() {
CryptoKey: sha256.Sum256([]byte("test")),
}
storage := mock.NewAuthStorage()
handler, err := op.NewDefaultOP(ctx, config, storage, op.WithCustomTokenEndpoint(op.NewEndpoint("test")))
handler, err := op.NewOpenIDProvider(ctx, config, storage, op.WithCustomTokenEndpoint(op.NewEndpoint("test")))
if err != nil {
log.Fatal(err)
}
Expand Down
16 changes: 7 additions & 9 deletions go.mod
Expand Up @@ -3,23 +3,21 @@ module github.com/caos/oidc
go 1.15

require (
github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a
github.com/caos/logging v0.0.2
github.com/golang/mock v1.4.4
github.com/google/go-cmp v0.4.1 // indirect
github.com/google/go-cmp v0.5.2 // indirect
github.com/google/go-github/v31 v31.0.0
github.com/google/uuid v1.1.2
github.com/gorilla/handlers v1.5.0
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/gorilla/securecookie v1.1.1
github.com/kr/pretty v0.1.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/sirupsen/logrus v1.6.0
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1 // indirect
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933
golang.org/x/oauth2 v0.0.0-20191122200657-5d9234df094c
golang.org/x/net v0.0.0-20200904194848-62affa334b73
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
golang.org/x/text v0.3.3
google.golang.org/appengine v1.6.5 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
gopkg.in/square/go-jose.v2 v2.5.1
)

0 comments on commit e96815f

Please sign in to comment.