やりたいこと
やりたいこととしては、GSuiteのアカウントで認証を一元管理したいなと。
そこでGsuiteのSSOを試してみたところ、色々と苦戦したので共有がてらに。
golangでSSOを試したかったのでその時のメモとして。
試しメモ
使ったライブラリはこれ
Gsuiteの設定はqiita teamのSSOから参考に
試したコードはこれ
Gsuiteの「ACS の URL * 」を、「AssertionConsumerServiceURL」にして
「エンティティ ID *」を「AudienceURI」にする。
sp := &saml2.SAMLServiceProvider{
IdentityProviderSSOURL: metadata.IDPSSODescriptor.SingleSignOnServices[0].Location,
IdentityProviderIssuer: metadata.EntityID,
ServiceProviderIssuer: "saml-test",
AssertionConsumerServiceURL: "https://localhost:8080/saml/consume",
SignAuthnRequests: true,
AudienceURI: "https://localhost:8080/saml/metadata",
IDPCertificateStore: &certStore,
SPKeyStore: randomKeyStore,
AllowMissingAttributes: true,
}
あとは、
BuildAuthURLでredirectさせて、認証したらAssertionConsumerServiceURLにPOSTされるのでparseするだけ
githubの方では色々と書いてあるけど、callbackされたところは
http.HandleFunc("/saml/consume", func(rw http.ResponseWriter, req *http.Request) {
fmt.Println("aaaa")
err := req.ParseForm()
if err != nil {
fmt.Println("ParseForm")
rw.WriteHeader(http.StatusBadRequest)
return
}
assertionInfo, err := sp.RetrieveAssertionInfo(req.FormValue("SAMLResponse"))
if err != nil {
fmt.Println("RetrieveAssertionInfo")
fmt.Println(err)
rw.WriteHeader(http.StatusForbidden)
return
}
if assertionInfo.WarningInfo.InvalidTime {
fmt.Println("InvalidTime")
rw.WriteHeader(http.StatusForbidden)
return
}
if assertionInfo.WarningInfo.NotInAudience {
fmt.Println("NotInAudience")
rw.WriteHeader(http.StatusForbidden)
return
}
fmt.Fprintf(rw, "NameID: %s\n", assertionInfo.NameID)
fmt.Fprintf(rw, "Assertions:\n")
for key, val := range assertionInfo.Values {
fmt.Fprintf(rw, " %s: %+v\n", key, val)
}
fmt.Fprintf(rw, "\n")
fmt.Fprintf(rw, "Warnings:\n")
fmt.Fprintf(rw, "%+v\n", assertionInfo.WarningInfo)
})
ValidateEncodedResponseとかはRetrieveAssertionInfoの中身をそのまま、どこでerrになるのか確認するためのprint debugです。
あとはここで、認証情報をセッションとかで保存しておけばやりたかったことが完成。