mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
feat(cloudid): add azure saml
This commit is contained in:
@@ -194,6 +194,27 @@ func prepareServer() error {
|
||||
Values: []string{v.value},
|
||||
})
|
||||
}
|
||||
case "urn:federation:MicrosoftOnline":
|
||||
data.NameId = sp.Username
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_PERSISTENT
|
||||
data.AudienceRestriction = sp.GetEntityId()
|
||||
for _, v := range []struct {
|
||||
name string
|
||||
friendlyName string
|
||||
value string
|
||||
}{
|
||||
{
|
||||
name: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
|
||||
value: data.NameId,
|
||||
},
|
||||
} {
|
||||
data.Attributes = append(data.Attributes, samlutils.SSAMLResponseAttribute{
|
||||
Name: v.name,
|
||||
FriendlyName: v.friendlyName,
|
||||
Values: []string{v.value},
|
||||
})
|
||||
}
|
||||
return data, nil
|
||||
case "google.com/a/yunion-hk.com":
|
||||
data.NameId = "qiujian"
|
||||
data.NameIdFormat = samlutils.NAME_ID_FORMAT_TRANSIENT
|
||||
@@ -406,6 +427,10 @@ func prepareServer() error {
|
||||
name: "Google cloud SSO",
|
||||
url: "https://www.google.com/a/yunion-hk.com/ServiceLogin?continue=https://console.cloud.google.com",
|
||||
},
|
||||
{
|
||||
name: "Azure cloud SSO",
|
||||
url: "https://login.microsoftonline.com/redeem?rd=https%3a%2f%2finvitations.microsoft.com%2fredeem%2f%3ftenant%3d17493ddf-fa90-4f95-8576-5df011c126e5%26user%3d3bc1c055-aa14-4795-aef0-5970b00d03c7%26ticket%3d0GDu%252bZ7nLbg01rYL5u%252b401%252bOLyZjxPewSBJIAZZ7E0U%253d%26ver%3d2.0",
|
||||
},
|
||||
} {
|
||||
htmlBuf.WriteString(fmt.Sprintf(`<li><a href="%s">%s (SP-Initiated)</a></li>`, v.url, v.name))
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ func (idp *SSAMLIdpInstance) AddHandlers(app *appsrv.Application, prefix string,
|
||||
if middleware != nil {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
app.AddHandler("POST", idp.redirectLoginPath, handler)
|
||||
app.AddHandler("GET", idp.redirectLoginPath, handler)
|
||||
handler = idp.redirectLogoutHandler
|
||||
if middleware != nil {
|
||||
@@ -224,16 +225,17 @@ func (idp *SSAMLIdpInstance) processLoginRequest(ctx context.Context, idpId stri
|
||||
return "", errors.Wrapf(httperrors.ErrInputParameter, "Destination not match: get %s want %s", authReq.Destination, idp.getRedirectLoginUrl(idpId))
|
||||
}
|
||||
|
||||
if authReq.AssertionConsumerServiceURL != sp.GetPostAssertionConsumerServiceUrl() {
|
||||
if len(authReq.AssertionConsumerServiceURL) > 0 && authReq.AssertionConsumerServiceURL != sp.GetPostAssertionConsumerServiceUrl() {
|
||||
return "", errors.Wrapf(httperrors.ErrInputParameter, "AssertionConsumerServiceURL not match: get %s want %s", authReq.AssertionConsumerServiceURL, sp.GetPostAssertionConsumerServiceUrl())
|
||||
}
|
||||
|
||||
sp.Username = input.Username
|
||||
resp, err := idp.getLoginResponse(ctx, authReq, idpId, sp)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "getLoginResponse")
|
||||
}
|
||||
|
||||
form, err := idp.samlResponse2Form(authReq.AssertionConsumerServiceURL, resp, input.RelayState)
|
||||
form, err := idp.samlResponse2Form(sp.GetPostAssertionConsumerServiceUrl(), resp, input.RelayState)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "samlResponse2Form")
|
||||
}
|
||||
@@ -246,7 +248,6 @@ func (idp *SSAMLIdpInstance) samlResponse2Form(url string, resp *samlutils.Respo
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "xml.Marshal")
|
||||
}
|
||||
|
||||
signed, err := idp.saml.SignXML(string(respXml))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "saml.SignXML")
|
||||
@@ -287,7 +288,7 @@ func (idp *SSAMLIdpInstance) getLoginResponse(ctx context.Context, req samlutils
|
||||
IssuerEntityId: idp.saml.GetEntityId(),
|
||||
RequestID: req.ID,
|
||||
RequestEntityId: req.Issuer.Issuer,
|
||||
AssertionConsumerServiceURL: req.AssertionConsumerServiceURL,
|
||||
AssertionConsumerServiceURL: sp.GetPostAssertionConsumerServiceUrl(),
|
||||
SSAMLSpInitiatedLoginData: data,
|
||||
}
|
||||
resp := samlutils.NewResponse(input)
|
||||
@@ -303,6 +304,9 @@ func (idp *SSAMLIdpInstance) processIdpInitiatedLogin(ctx context.Context, input
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "idp.onIdpInitiatedLogin")
|
||||
}
|
||||
if len(data.Form) > 0 {
|
||||
return data.Form, nil
|
||||
}
|
||||
respInput := samlutils.SSAMLResponseInput{
|
||||
IssuerCertString: idp.saml.GetCertString(),
|
||||
IssuerEntityId: idp.saml.GetEntityId(),
|
||||
|
||||
@@ -23,6 +23,8 @@ import (
|
||||
|
||||
type SSAMLServiceProvider struct {
|
||||
desc samlutils.EntityDescriptor
|
||||
|
||||
Username string
|
||||
}
|
||||
|
||||
func (sp *SSAMLServiceProvider) GetEntityId() string {
|
||||
|
||||
@@ -36,6 +36,8 @@ type SSAMLSpInitiatedLoginData struct {
|
||||
AudienceRestriction string
|
||||
|
||||
Attributes []SSAMLResponseAttribute
|
||||
|
||||
Form string
|
||||
}
|
||||
|
||||
type SSAMLIdpInitiatedLoginData struct {
|
||||
@@ -59,7 +61,7 @@ type SSAMLResponseInput struct {
|
||||
|
||||
func NewResponse(input SSAMLResponseInput) Response {
|
||||
// since := timeutils.IsoTime(time.Now().UTC().Add(-time.Minute * 60 * 24))
|
||||
until := timeutils.IsoTime(time.Now().UTC().Add(time.Minute * 60 * 24))
|
||||
until := timeutils.IsoTime(time.Now().UTC().Add(time.Minute * 5))
|
||||
|
||||
respId := GenerateSAMLId()
|
||||
assertId := GenerateSAMLId()
|
||||
@@ -251,6 +253,7 @@ func NewResponse(input SSAMLResponseInput) Response {
|
||||
Space: XMLNS_ASSERT,
|
||||
Local: "Conditions",
|
||||
},
|
||||
NotBefore: &now,
|
||||
NotOnOrAfter: until,
|
||||
AudienceRestrictions: []AudienceRestriction{},
|
||||
},
|
||||
|
||||
@@ -250,6 +250,8 @@ type SIdpRedirectLoginInput struct {
|
||||
RelayState string `json:"RelayState,ignoreempty"`
|
||||
SigAlg string `json:"SigAlg,ignoreempty"`
|
||||
Signature string `json:"Signature,ignoreempty"`
|
||||
|
||||
Username string `json:"username,ignoreempty"`
|
||||
}
|
||||
|
||||
type SIdpInitiatedLoginInput struct {
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
"github.com/ma314smith/signedxml"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
@@ -72,11 +73,15 @@ func SAMLDecode(input string) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "base64.StdEncoding.DecodeString")
|
||||
}
|
||||
plainText, err := decompress(reqBytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "decompress")
|
||||
}
|
||||
return plainText, nil
|
||||
return func() []byte {
|
||||
// Azure no need to decompress
|
||||
plainText, err := decompress(reqBytes)
|
||||
if err != nil {
|
||||
log.Warningf("decompress %s error: %v", string(reqBytes), err)
|
||||
return reqBytes
|
||||
}
|
||||
return plainText
|
||||
}(), nil
|
||||
}
|
||||
|
||||
func SAMLEncode(input []byte) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user