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

feat: jwt profile grant #56

Merged
merged 38 commits into from Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7a109a7
feat: service account token exchange
adlerhurst Sep 2, 2020
6a0dd7c
Merge branch 'master' into service-accounts
livio-a Sep 7, 2020
7487af3
add func for creating JWT token
adlerhurst Sep 7, 2020
9cb0fff
Merge remote-tracking branch 'origin/service-accounts' into service-a…
livio-a Sep 7, 2020
a37a846
lot of unfinished changes
livio-a Sep 8, 2020
bfbd4ad
some ideas to implement jwt client assertion
livio-a Sep 8, 2020
eaf47fd
change some interfaces
livio-a Sep 9, 2020
7700cb3
fix: implement storage
adlerhurst Sep 10, 2020
9d8fc4f
Merge branch 'master' into service-accounts
adlerhurst Sep 10, 2020
6be292a
Merge branch 'master' into service-accounts
livio-a Sep 10, 2020
f870795
Merge remote-tracking branch 'origin/service-accounts' into service-a…
livio-a Sep 10, 2020
a731a46
fix: aud
adlerhurst Sep 10, 2020
3777f14
Merge remote-tracking branch 'origin/service-accounts' into service-a…
livio-a Sep 10, 2020
17a72cc
fix: storage interface
adlerhurst Sep 10, 2020
143ff34
change verifier interfaces
livio-a Sep 11, 2020
ed6cbe4
Merge remote-tracking branch 'origin/service-accounts' into service-a…
livio-a Sep 14, 2020
4523056
change RP interfaces
livio-a Sep 14, 2020
8790b54
update some op interfaces
livio-a Sep 15, 2020
5a98ec4
add missing error handling
livio-a Sep 15, 2020
3c2ad6a
update app example
livio-a Sep 15, 2020
2dfdaa2
fix state handling in auth request
livio-a Sep 15, 2020
5a9e6e2
let tests work
livio-a Sep 15, 2020
2e6d1f8
fix server example
livio-a Sep 15, 2020
87b30dc
fix cli
livio-a Sep 15, 2020
a56a4a0
harmonize jwtProfile and existing interfaces / functions
livio-a Sep 15, 2020
cae42cc
fix: parse error
adlerhurst Sep 15, 2020
2e75f54
update mocks
livio-a Sep 16, 2020
d97df8a
Merge remote-tracking branch 'origin/service-accounts' into service-a…
livio-a Sep 16, 2020
693ce1a
differ between oauth2 and oidc relaying party
livio-a Sep 16, 2020
fd3daa2
fix: jwt profile request in op
adlerhurst Sep 16, 2020
ad0966c
Merge branch 'service-accounts' of github.com:caos/oidc into service-…
adlerhurst Sep 16, 2020
5b6175a
fix: dependencies
adlerhurst Sep 16, 2020
4a917fb
Update pkg/rp/tockenexchange.go
adlerhurst Sep 16, 2020
64797c1
cleanup
livio-a Sep 16, 2020
0547bfb
Merge remote-tracking branch 'origin/service-accounts' into service-a…
livio-a Sep 16, 2020
779ad70
add NewJWTProfileAssertionFromKeyJSON
livio-a Sep 16, 2020
28f731c
fix: remove test because we know it works. :P
adlerhurst Sep 16, 2020
c90a9d5
cleanup
livio-a Sep 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
)