fix: empty iss return (#503)

Signed-off-by: Steve0x2a <stevesough@gmail.com>
This commit is contained in:
Steve0x2a 2022-02-18 12:36:11 +08:00 committed by GitHub
parent 661abd6b6e
commit 274096fe9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 2108 additions and 61 deletions

View File

@ -18,9 +18,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strconv" "strconv"
"strings"
"github.com/astaxie/beego"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
) )
@ -69,18 +67,6 @@ type Response struct {
Data2 interface{} `json:"data2"` Data2 interface{} `json:"data2"`
} }
type Userinfo struct {
Sub string `json:"sub"`
Iss string `json:"iss"`
Aud string `json:"aud"`
Name string `json:"name,omitempty"`
DisplayName string `json:"preferred_username,omitempty"`
Email string `json:"email,omitempty"`
Avatar string `json:"picture,omitempty"`
Address string `json:"address,omitempty"`
Phone string `json:"phone,omitempty"`
}
type HumanCheck struct { type HumanCheck struct {
Type string `json:"type"` Type string `json:"type"`
AppKey string `json:"appKey"` AppKey string `json:"appKey"`
@ -254,38 +240,18 @@ func (c *ApiController) GetAccount() {
// @Title UserInfo // @Title UserInfo
// @Tag Account API // @Tag Account API
// @Description return user information according to OIDC standards // @Description return user information according to OIDC standards
// @Success 200 {object} controllers.Userinfo The Response object // @Success 200 {object} object.Userinfo The Response object
// @router /userinfo [get] // @router /userinfo [get]
func (c *ApiController) GetUserinfo() { func (c *ApiController) GetUserinfo() {
userId, ok := c.RequireSignedIn() userId, ok := c.RequireSignedIn()
if !ok { if !ok {
return return
} }
user := object.GetUser(userId)
if user == nil {
c.ResponseError(fmt.Sprintf("The user: %s doesn't exist", userId))
return
}
scope, aud := c.GetSessionOidc() scope, aud := c.GetSessionOidc()
iss := beego.AppConfig.String("origin") host := c.Ctx.Request.Host
resp := Userinfo{ resp, err := object.GetUserInfo(userId, scope, aud, host)
Sub: user.Id, if err != nil {
Iss: iss, c.ResponseError(err.Error())
Aud: aud,
}
if strings.Contains(scope, "profile") {
resp.Name = user.Name
resp.DisplayName = user.DisplayName
resp.Avatar = user.Avatar
}
if strings.Contains(scope, "email") {
resp.Email = user.Email
}
if strings.Contains(scope, "address") {
resp.Address = user.Location
}
if strings.Contains(scope, "phone") {
resp.Phone = user.Phone
} }
c.Data["json"] = resp c.Data["json"] = resp
c.ServeJSON() c.ServeJSON()

View File

@ -59,7 +59,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
c.ResponseError("Challenge method should be S256") c.ResponseError("Challenge method should be S256")
return return
} }
code := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge) code := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host)
resp = codeToResponse(code) resp = codeToResponse(code)
if application.EnableSigninSession || application.HasPromptPage() { if application.EnableSigninSession || application.HasPromptPage() {

View File

@ -149,8 +149,9 @@ func (c *ApiController) GetOAuthCode() {
c.ResponseError("Challenge method should be S256") c.ResponseError("Challenge method should be S256")
return return
} }
host := c.Ctx.Request.Host
c.Data["json"] = object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge) c.Data["json"] = object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, host)
c.ServeJSON() c.ServeJSON()
} }
@ -195,7 +196,8 @@ func (c *ApiController) RefreshToken() {
scope := c.Input().Get("scope") scope := c.Input().Get("scope")
clientId := c.Input().Get("client_id") clientId := c.Input().Get("client_id")
clientSecret := c.Input().Get("client_secret") clientSecret := c.Input().Get("client_secret")
host := c.Ctx.Request.Host
c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret) c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
c.ServeJSON() c.ServeJSON()
} }

View File

@ -69,7 +69,7 @@ func GetOidcDiscovery(host string) OidcDiscovery {
// https://accounts.google.com/.well-known/openid-configuration // https://accounts.google.com/.well-known/openid-configuration
// https://access.line.me/.well-known/openid-configuration // https://access.line.me/.well-known/openid-configuration
oidcDiscovery := OidcDiscovery{ oidcDiscovery := OidcDiscovery{
Issuer: originFrontend, Issuer: originBackend,
AuthorizationEndpoint: fmt.Sprintf("%s/login/oauth/authorize", originFrontend), AuthorizationEndpoint: fmt.Sprintf("%s/login/oauth/authorize", originFrontend),
TokenEndpoint: fmt.Sprintf("%s/api/login/oauth/access_token", originBackend), TokenEndpoint: fmt.Sprintf("%s/api/login/oauth/access_token", originBackend),
UserinfoEndpoint: fmt.Sprintf("%s/api/userinfo", originBackend), UserinfoEndpoint: fmt.Sprintf("%s/api/userinfo", originBackend),

View File

@ -204,7 +204,7 @@ func CheckOAuthLogin(clientId string, responseType string, redirectUri string, s
return "", application return "", application
} }
func GetOAuthCode(userId string, clientId string, responseType string, redirectUri string, scope string, state string, nonce string, challenge string) *Code { func GetOAuthCode(userId string, clientId string, responseType string, redirectUri string, scope string, state string, nonce string, challenge string, host string) *Code {
user := GetUser(userId) user := GetUser(userId)
if user == nil { if user == nil {
return &Code{ return &Code{
@ -227,7 +227,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
} }
} }
accessToken, refreshToken, err := generateJwtToken(application, user, nonce, scope) accessToken, refreshToken, err := generateJwtToken(application, user, nonce, scope, host)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -361,7 +361,7 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
return tokenWrapper return tokenWrapper
} }
func RefreshToken(grantType string, refreshToken string, scope string, clientId string, clientSecret string) *TokenWrapper { func RefreshToken(grantType string, refreshToken string, scope string, clientId string, clientSecret string, host string) *TokenWrapper {
// check parameters // check parameters
if grantType != "refresh_token" { if grantType != "refresh_token" {
return &TokenWrapper{ return &TokenWrapper{
@ -420,7 +420,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
Scope: "", Scope: "",
} }
} }
newAccessToken, newRefreshToken, err := generateJwtToken(application, user, "", scope) newAccessToken, newRefreshToken, err := generateJwtToken(application, user, "", scope, host)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -61,12 +61,17 @@ func getShortClaims(claims Claims) ClaimsShort {
return res return res
} }
func generateJwtToken(application *Application, user *User, nonce string, scope string) (string, string, error) { func generateJwtToken(application *Application, user *User, nonce string, scope string, host string) (string, string, error) {
nowTime := time.Now() nowTime := time.Now()
expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour) expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour)
refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour) refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour)
user.Password = "" user.Password = ""
origin := beego.AppConfig.String("origin")
_, originBackend := getOriginFromHost(host)
if origin != "" {
originBackend = origin
}
claims := Claims{ claims := Claims{
User: user, User: user,
@ -75,7 +80,7 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
Tag: user.Tag, Tag: user.Tag,
Scope: scope, Scope: scope,
RegisteredClaims: jwt.RegisteredClaims{ RegisteredClaims: jwt.RegisteredClaims{
Issuer: beego.AppConfig.String("origin"), Issuer: originBackend,
Subject: user.Id, Subject: user.Id,
Audience: []string{application.ClientId}, Audience: []string{application.ClientId},
ExpiresAt: jwt.NewNumericDate(expireTime), ExpiresAt: jwt.NewNumericDate(expireTime),

View File

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/astaxie/beego"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
"xorm.io/core" "xorm.io/core"
) )
@ -90,6 +91,18 @@ type User struct {
Properties map[string]string `json:"properties"` Properties map[string]string `json:"properties"`
} }
type Userinfo struct {
Sub string `json:"sub"`
Iss string `json:"iss"`
Aud string `json:"aud"`
Name string `json:"name,omitempty"`
DisplayName string `json:"preferred_username,omitempty"`
Email string `json:"email,omitempty"`
Avatar string `json:"picture,omitempty"`
Address string `json:"address,omitempty"`
Phone string `json:"phone,omitempty"`
}
func GetGlobalUserCount(field, value string) int { func GetGlobalUserCount(field, value string) int {
session := GetSession("", -1, -1, field, value, "", "") session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Count(&User{}) count, err := session.Count(&User{})
@ -402,6 +415,39 @@ func DeleteUser(user *User) bool {
return affected != 0 return affected != 0
} }
func GetUserInfo(userId string, scope string, aud string, host string) (*Userinfo, error) {
user := GetUser(userId)
if user == nil {
return nil, fmt.Errorf("the user: %s doesn't exist", userId)
}
origin := beego.AppConfig.String("origin")
_, originBackend := getOriginFromHost(host)
if origin != "" {
originBackend = origin
}
resp := Userinfo{
Sub: user.Id,
Iss: originBackend,
Aud: aud,
}
if strings.Contains(scope, "profile") {
resp.Name = user.Name
resp.DisplayName = user.DisplayName
resp.Avatar = user.Avatar
}
if strings.Contains(scope, "email") {
resp.Email = user.Email
}
if strings.Contains(scope, "address") {
resp.Address = user.Location
}
if strings.Contains(scope, "phone") {
resp.Phone = user.Phone
}
return &resp, nil
}
func LinkUserAccount(user *User, field string, value string) bool { func LinkUserAccount(user *User, field string, value string) bool {
return SetUserField(user, field, value) return SetUserField(user, field, value)
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff