mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-19 23:28:20 +01:00
Redirect regular user to OIDC login page (#7717)
When the auth mode is OIDC, when a user login via Harbor's login form. If the user does not exist or the user is onboarded via OIDC, he will be redirected to the OIDC login page. Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
parent
1828537672
commit
cbbf2ea973
@ -139,6 +139,7 @@ const (
|
|||||||
RobotTokenDuration = "robot_token_duration"
|
RobotTokenDuration = "robot_token_duration"
|
||||||
|
|
||||||
OIDCCallbackPath = "/c/oidc/callback"
|
OIDCCallbackPath = "/c/oidc/callback"
|
||||||
|
OIDCLoginPath = "/c/oidc/login"
|
||||||
|
|
||||||
ChartUploadCtxKey = contextKey("chart_upload_event")
|
ChartUploadCtxKey = contextKey("chart_upload_event")
|
||||||
)
|
)
|
||||||
|
@ -16,12 +16,15 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"github.com/goharbor/harbor/src/core/filter"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
"github.com/beego/i18n"
|
"github.com/beego/i18n"
|
||||||
@ -54,10 +57,43 @@ type messageDetail struct {
|
|||||||
UUID string
|
UUID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func redirectForOIDC(ctx context.Context, username string) bool {
|
||||||
|
am, _ := ctx.Value(filter.AuthModeKey).(string)
|
||||||
|
if am != common.OIDCAuth {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
u, err := dao.GetUser(models.User{Username: username})
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("Failed to get user by name: %s, error: %v", username, err)
|
||||||
|
}
|
||||||
|
if u == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ou, err := dao.GetOIDCUserByUserID(u.UserID)
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("Failed to get OIDC user info for user, id: %d, error: %v", u.UserID, err)
|
||||||
|
}
|
||||||
|
if ou != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Login handles login request from UI.
|
// Login handles login request from UI.
|
||||||
func (cc *CommonController) Login() {
|
func (cc *CommonController) Login() {
|
||||||
principal := cc.GetString("principal")
|
principal := cc.GetString("principal")
|
||||||
password := cc.GetString("password")
|
password := cc.GetString("password")
|
||||||
|
if redirectForOIDC(cc.Ctx.Request.Context(), principal) {
|
||||||
|
ep, err := config.ExtEndpoint()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to get the external endpoint, error: %v", err)
|
||||||
|
cc.CustomAbort(http.StatusUnauthorized, "")
|
||||||
|
}
|
||||||
|
url := strings.TrimSuffix(ep, "/") + common.OIDCLoginPath
|
||||||
|
log.Debugf("Redirect user %s to login page of OIDC provider", principal)
|
||||||
|
cc.Redirect(url, http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
user, err := auth.Login(models.AuthModel{
|
user, err := auth.Login(models.AuthModel{
|
||||||
Principal: principal,
|
Principal: principal,
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/goharbor/harbor/src/core/filter"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
// "net/url"
|
// "net/url"
|
||||||
@ -90,6 +92,15 @@ func TestUserResettable(t *testing.T) {
|
|||||||
assert.True(isUserResetable(u1))
|
assert.True(isUserResetable(u1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRedirectForOIDC(t *testing.T) {
|
||||||
|
ctx := context.WithValue(context.Background(), filter.AuthModeKey, common.DBAuth)
|
||||||
|
assert.False(t, redirectForOIDC(ctx, "nonexist"))
|
||||||
|
ctx = context.WithValue(context.Background(), filter.AuthModeKey, common.OIDCAuth)
|
||||||
|
assert.True(t, redirectForOIDC(ctx, "nonexist"))
|
||||||
|
assert.False(t, redirectForOIDC(ctx, "admin"))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// TestMain is a sample to run an endpoint test
|
// TestMain is a sample to run an endpoint test
|
||||||
func TestAll(t *testing.T) {
|
func TestAll(t *testing.T) {
|
||||||
config.InitWithSettings(utilstest.GetUnitTestConfig())
|
config.InitWithSettings(utilstest.GetUnitTestConfig())
|
||||||
|
@ -38,7 +38,7 @@ func initRouters() {
|
|||||||
beego.Router("/c/reset", &controllers.CommonController{}, "post:ResetPassword")
|
beego.Router("/c/reset", &controllers.CommonController{}, "post:ResetPassword")
|
||||||
beego.Router("/c/userExists", &controllers.CommonController{}, "post:UserExists")
|
beego.Router("/c/userExists", &controllers.CommonController{}, "post:UserExists")
|
||||||
beego.Router("/c/sendEmail", &controllers.CommonController{}, "get:SendResetEmail")
|
beego.Router("/c/sendEmail", &controllers.CommonController{}, "get:SendResetEmail")
|
||||||
beego.Router("/c/oidc/login", &controllers.OIDCController{}, "get:RedirectLogin")
|
beego.Router(common.OIDCLoginPath, &controllers.OIDCController{}, "get:RedirectLogin")
|
||||||
beego.Router("/c/oidc/onboard", &controllers.OIDCController{}, "post:Onboard")
|
beego.Router("/c/oidc/onboard", &controllers.OIDCController{}, "post:Onboard")
|
||||||
beego.Router(common.OIDCCallbackPath, &controllers.OIDCController{}, "get:Callback")
|
beego.Router(common.OIDCCallbackPath, &controllers.OIDCController{}, "get:Callback")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user