Skip to content

Commit 6a400c5

Browse files
author
Pavol Ipoth
committed
Add password grant for oidc provider
1 parent 38062e1 commit 6a400c5

File tree

3 files changed

+162
-12
lines changed

3 files changed

+162
-12
lines changed

pkg/libs/oidc-provider/plugin.go

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package oidcprovider
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
7+
"io/ioutil"
68
"os"
79
"sync"
810
"time"
@@ -44,36 +46,32 @@ type TokenProviderOptions struct {
4446
TargetAudience string
4547
}
4648

49+
type GrantType struct {
50+
Name string `json:"grant_type"`
51+
}
52+
4753
// NewTokenProvider - Generate new OIDC token provider
4854
func NewTokenProvider(options TokenProviderOptions) (*TokenProvider, error) {
4955
os.Setenv("OIDC_CREDENTIALS", options.CredentialsFile)
5056
stopChannel := make(chan bool, 1)
5157
var idTokenSource idTokenSource
5258

53-
serviceAccountSource, err := NewServiceAccountSource(
54-
options.CredentialsFile,
55-
options.TargetAudience)
56-
57-
idTokenSource = serviceAccountSource
59+
idTokenSource, err := getTokenSource(options.CredentialsFile, options.TargetAudience)
5860

5961
if err != nil {
60-
return nil, errors.Wrap(err, "creation of service account source failed")
62+
return nil, err
6163
}
6264

6365
if options.CredentialsWatch {
6466
action := func() {
6567
logrus.Infof("reloading credential file %s", options.CredentialsFile)
6668

67-
newConfig, errServ := oidc.NewServiceAccountTokenSource(
68-
options.CredentialsFile,
69-
options.TargetAudience)
69+
idTokenSource, err = getTokenSource(options.CredentialsFile, options.TargetAudience)
7070

71-
if errServ != nil {
71+
if err != nil {
7272
logrus.Errorf("error while reloading credentials files: %s", err)
7373
return
7474
}
75-
76-
serviceAccountSource.setServiceAccountTokenSource(newConfig)
7775
}
7876

7977
err = util.WatchForUpdates(options.CredentialsFile, stopChannel, action)
@@ -211,6 +209,45 @@ func getTokenResponse(token string, status int) (apis.TokenResponse, error) {
211209
return apis.TokenResponse{Success: success, Status: int32(status), Token: token}, nil
212210
}
213211

212+
func getTokenSource(credentialsFilePath string, targetAud string) (idTokenSource, error) {
213+
data, err := ioutil.ReadFile(credentialsFilePath)
214+
215+
if err != nil {
216+
return nil, err
217+
}
218+
219+
grantType := &GrantType{}
220+
221+
err = json.Unmarshal(data, grantType)
222+
223+
if err != nil {
224+
return nil, err
225+
}
226+
227+
switch grantType.Name {
228+
case "password":
229+
passwordGrantSource, err := NewPasswordGrantSource(
230+
credentialsFilePath,
231+
targetAud)
232+
233+
if err != nil {
234+
return nil, errors.Wrap(err, "creation of password grant source failed")
235+
}
236+
237+
return passwordGrantSource, nil
238+
default:
239+
serviceAccountSource, err := NewServiceAccountSource(
240+
credentialsFilePath,
241+
targetAud)
242+
243+
if err != nil {
244+
return nil, errors.Wrap(err, "creation of service account source failed")
245+
}
246+
247+
return serviceAccountSource, nil
248+
}
249+
}
250+
214251
type idTokenSource interface {
215252
GetIDToken(ctx context.Context) (string, error)
216253
}
@@ -249,3 +286,38 @@ func NewServiceAccountSource(credentialsFile string, targetAudience string) (*se
249286
func (s *serviceAccountSource) GetIDToken(parent context.Context) (string, error) {
250287
return s.getServiceAccountTokenSource().GetIDToken(parent)
251288
}
289+
290+
type passwordGrantSource struct {
291+
source *oidc.PasswordGrantTokenSource
292+
l sync.RWMutex
293+
}
294+
295+
func (p *passwordGrantSource) getPasswordGrantTokenSource() *oidc.PasswordGrantTokenSource {
296+
p.l.RLock()
297+
defer p.l.RUnlock()
298+
299+
return p.source
300+
}
301+
302+
func (p *passwordGrantSource) setPasswordGrantTokenSource(source *oidc.PasswordGrantTokenSource) {
303+
p.l.Lock()
304+
defer p.l.Unlock()
305+
306+
p.source = source
307+
}
308+
309+
func NewPasswordGrantSource(credentialsFile string, targetAudience string) (*passwordGrantSource, error) {
310+
source, err := oidc.NewPasswordGrantTokenSource(credentialsFile, targetAudience)
311+
312+
if err != nil {
313+
return nil, err
314+
}
315+
316+
return &passwordGrantSource{
317+
source: source,
318+
}, nil
319+
}
320+
321+
func (s *passwordGrantSource) GetIDToken(parent context.Context) (string, error) {
322+
return s.getPasswordGrantTokenSource().GetIDToken(parent)
323+
}

pkg/libs/oidc/password_grant.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package oidc
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"errors"
7+
"io/ioutil"
8+
9+
"github.com/sirupsen/logrus"
10+
"golang.org/x/oauth2"
11+
)
12+
13+
type PasswordGrantTokenSource struct {
14+
ClientID string `json:"client_id"`
15+
16+
ClientSecret string `json:"client_secret"`
17+
18+
Username string `json:"username"`
19+
20+
Password string `json:"password"`
21+
22+
// TokenURL is the resource server's token endpoint
23+
// URL. This is a constant specific to each server.
24+
TokenURL string `json:"token_url"`
25+
26+
// Scope specifies optional requested permissions.
27+
Scopes []string `json:"scopes"`
28+
}
29+
30+
func NewPasswordGrantTokenSource(credentialsFile string, targetAudience string) (*PasswordGrantTokenSource, error) {
31+
data, err := ioutil.ReadFile(credentialsFile)
32+
source := &PasswordGrantTokenSource{}
33+
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
err = json.Unmarshal(data, source)
39+
40+
if err != nil {
41+
return nil, err
42+
}
43+
44+
return source, nil
45+
}
46+
47+
// GetIDToken - retrieve token from endpoint
48+
func (s *PasswordGrantTokenSource) GetIDToken(parent context.Context) (string, error) {
49+
conf := &oauth2.Config{
50+
Scopes: s.Scopes,
51+
ClientID: s.ClientID,
52+
ClientSecret: s.ClientSecret,
53+
Endpoint: oauth2.Endpoint{
54+
TokenURL: s.TokenURL,
55+
},
56+
}
57+
58+
logrus.Debugf("Configuration is %v", conf)
59+
60+
token, err := conf.PasswordCredentialsToken(parent, s.Username, s.Password)
61+
62+
if err != nil {
63+
logrus.Errorf("Retrieving oidc token failed %v", err)
64+
return "", err
65+
}
66+
67+
var idTokenRes struct {
68+
IDToken string `json:"id_token"`
69+
}
70+
71+
if token.AccessToken == "" {
72+
return "", errors.New("oidc access_token is missing")
73+
}
74+
75+
idTokenRes.IDToken = token.AccessToken
76+
77+
return idTokenRes.IDToken, nil
78+
}

0 commit comments

Comments
 (0)