Add filter to handle request with ID token (#7759)

This commit allows request with a valid ID token to access the API.

Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
Daniel Jiang 2019-05-10 16:58:25 +08:00 committed by Wang Yan
parent 439b44c61f
commit d81afe274c
3 changed files with 63 additions and 1 deletions

View File

@ -91,6 +91,8 @@ func (oc *OIDCController) Callback() {
oc.SendBadRequestError(err) oc.SendBadRequestError(err)
return return
} }
log.Debugf("ID token from provider: %s", token.IDToken)
idToken, err := oidc.VerifyToken(ctx, token.IDToken) idToken, err := oidc.VerifyToken(ctx, token.IDToken)
if err != nil { if err != nil {
oc.SendInternalServerError(err) oc.SendInternalServerError(err)
@ -118,7 +120,6 @@ func (oc *OIDCController) Callback() {
oc.SendInternalServerError(err) oc.SendInternalServerError(err)
return return
} }
log.Debugf("Exchanged token string: %s", string(tokenBytes))
oc.SetSession(tokenKey, tokenBytes) oc.SetSession(tokenKey, tokenBytes)
if u == nil { if u == nil {

View File

@ -115,6 +115,7 @@ func Init() {
&configCtxModifier{}, &configCtxModifier{},
&secretReqCtxModifier{config.SecretStore}, &secretReqCtxModifier{config.SecretStore},
&oidcCliReqCtxModifier{}, &oidcCliReqCtxModifier{},
&idTokenReqCtxModifier{},
&authProxyReqCtxModifier{}, &authProxyReqCtxModifier{},
&robotAuthReqCtxModifier{}, &robotAuthReqCtxModifier{},
&basicAuthReqCtxModifier{}, &basicAuthReqCtxModifier{},
@ -260,6 +261,41 @@ func (oc *oidcCliReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
return true return true
} }
type idTokenReqCtxModifier struct{}
func (it *idTokenReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
req := ctx.Request
if req.Context().Value(AuthModeKey).(string) != common.OIDCAuth {
return false
}
if !strings.HasPrefix(ctx.Request.URL.Path, "/api") {
return false
}
h := req.Header.Get("Authorization")
token := strings.Split(h, "Bearer")
if len(token) < 2 {
return false
}
claims, err := oidc.VerifyToken(req.Context(), strings.TrimSpace(token[1]))
if err != nil {
log.Warningf("Failed to verify token, error: %v", err)
return false
}
u, err := dao.GetUserBySubIss(claims.Subject, claims.Issuer)
if err != nil {
log.Warningf("Failed to get user based on token claims, error: %v", err)
return false
}
if u == nil {
log.Warning("User matches token's claims is not onboarded.")
return false
}
pm := config.GlobalProjectMgr
sc := local.NewSecurityContext(u, pm)
setSecurCtxAndPM(ctx.Request, sc, pm)
return true
}
type authProxyReqCtxModifier struct{} type authProxyReqCtxModifier struct{}
func (ap *authProxyReqCtxModifier) Modify(ctx *beegoctx.Context) bool { func (ap *authProxyReqCtxModifier) Modify(ctx *beegoctx.Context) bool {

View File

@ -192,6 +192,31 @@ func TestOIDCCliReqCtxModifier(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
} }
func TestIdTokenReqCtxModifier(t *testing.T) {
bc := context.Background()
it := &idTokenReqCtxModifier{}
r1, err := http.NewRequest(http.MethodGet,
"http://127.0.0.1/chartrepo/", nil)
require.Nil(t, err)
req1 := r1.WithContext(context.WithValue(bc, AuthModeKey, common.DBAuth))
ctx1, err := newContext(req1)
require.Nil(t, err)
assert.False(t, it.Modify(ctx1))
req2 := r1.WithContext(context.WithValue(bc, AuthModeKey, common.OIDCAuth))
ctx2, err := newContext(req2)
require.Nil(t, err)
assert.False(t, it.Modify(ctx2))
r2, err := http.NewRequest(http.MethodGet,
"http://127.0.0.1/api/projects/", nil)
require.Nil(t, err)
req3 := r2.WithContext(context.WithValue(bc, AuthModeKey, common.OIDCAuth))
ctx3, err := newContext(req3)
require.Nil(t, err)
assert.False(t, it.Modify(ctx3))
}
func TestRobotReqCtxModifier(t *testing.T) { func TestRobotReqCtxModifier(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, req, err := http.NewRequest(http.MethodGet,
"http://127.0.0.1/api/projects/", nil) "http://127.0.0.1/api/projects/", nil)