mirror of
https://github.com/smallstep/certificates.git
synced 2024-11-11 07:11:00 +00:00
Add support for functions in OIDC token transformation template
This commit is contained in:
parent
d5b0d92bce
commit
29202eff26
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"go.step.sm/crypto/x509util"
|
||||
)
|
||||
|
||||
type Provider struct {
|
||||
@ -85,11 +86,7 @@ func (o *OIDCOptions) validateAndInitialize() (err error) {
|
||||
return fmt.Errorf("failed parsing OIDC template: %w", err)
|
||||
}
|
||||
|
||||
transformTemplate := defaultTemplate
|
||||
if o.TransformTemplate != "" {
|
||||
transformTemplate = o.TransformTemplate
|
||||
}
|
||||
o.transform, err = template.New("transform").Parse(transformTemplate)
|
||||
o.transform, err = parseTransform(o.TransformTemplate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed parsing OIDC transformation template: %w", err)
|
||||
}
|
||||
@ -97,6 +94,14 @@ func (o *OIDCOptions) validateAndInitialize() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseTransform(transformTemplate string) (*template.Template, error) {
|
||||
if transformTemplate == "" {
|
||||
transformTemplate = defaultTemplate
|
||||
}
|
||||
|
||||
return template.New("transform").Funcs(x509util.GetFuncMap()).Parse(transformTemplate)
|
||||
}
|
||||
|
||||
func (o *OIDCOptions) EvaluateTarget(deviceID string) (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := o.target.Execute(buf, struct{ DeviceID string }{DeviceID: deviceID}); err != nil {
|
||||
@ -109,6 +114,7 @@ func (o *OIDCOptions) Transform(v map[string]any) (map[string]any, error) {
|
||||
if o.transform == nil || v == nil {
|
||||
return v, nil
|
||||
}
|
||||
// TODO(hs): add support for extracting error message from template "fail" function?
|
||||
buf := new(bytes.Buffer)
|
||||
if err := o.transform.Execute(buf, v); err != nil {
|
||||
return nil, fmt.Errorf("failed executing OIDC transformation: %w", err)
|
||||
|
@ -9,9 +9,11 @@ import (
|
||||
)
|
||||
|
||||
func TestOIDCOptions_Transform(t *testing.T) {
|
||||
defaultTransform, err := template.New("defaultTransform").Parse(`{"name": "{{ .name }}", "handle": "{{ .preferred_username }}"}`)
|
||||
defaultTransform, err := parseTransform(``)
|
||||
require.NoError(t, err)
|
||||
swapTransform, err := template.New("swapTransform").Parse(`{"name": "{{ .preferred_username }}", "handle": "{{ .name }}"}`)
|
||||
swapTransform, err := parseTransform(`{"name": "{{ .preferred_username }}", "handle": "{{ .name }}"}`)
|
||||
require.NoError(t, err)
|
||||
funcTransform, err := parseTransform(`{"name": "{{ .name }}", "handle": "{{ first .usernames }}"}`)
|
||||
require.NoError(t, err)
|
||||
type fields struct {
|
||||
transform *template.Template
|
||||
@ -86,6 +88,23 @@ func TestOIDCOptions_Transform(t *testing.T) {
|
||||
"preferred_username": "Preferred",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok/transform-with-functions",
|
||||
fields: fields{
|
||||
transform: funcTransform,
|
||||
},
|
||||
args: args{
|
||||
v: map[string]any{
|
||||
"name": "Example",
|
||||
"usernames": []string{"name-1", "name-2", "name-3"},
|
||||
},
|
||||
},
|
||||
want: map[string]any{
|
||||
"name": "Example",
|
||||
"handle": "name-1",
|
||||
"usernames": []string{"name-1", "name-2", "name-3"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user