111 lines
2.7 KiB
Go
111 lines
2.7 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"crypto/hmac"
|
||
|
"crypto/sha256"
|
||
|
"encoding/hex"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
)
|
||
|
|
||
|
func ssoCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
payloadHex := r.FormValue("payload")
|
||
|
signature := r.FormValue("hmac")
|
||
|
|
||
|
payloadBytes, err := hex.DecodeString(payloadHex)
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(w, "Error: invalid JSON payload hex encoding: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
signatureBytes, err := hex.DecodeString(signature)
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(w, "Error: invalid HMAC signature hex encoding: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
payload := ssoPayload{}
|
||
|
err = json.Unmarshal(payloadBytes, &payload)
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(w, "Error: cannot unmarshal JSON payload: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if payload.Domain == "" || payload.Token == "" || payload.Email == "" || payload.Name == "" {
|
||
|
fmt.Fprintf(w, "Error: %s\n", errorMissingField.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if payload.Link == "" {
|
||
|
payload.Link = "undefined"
|
||
|
}
|
||
|
|
||
|
if payload.Photo == "" {
|
||
|
payload.Photo = "undefined"
|
||
|
}
|
||
|
|
||
|
d, err := domainGet(payload.Domain)
|
||
|
if err != nil {
|
||
|
if err == errorNoSuchDomain {
|
||
|
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||
|
} else {
|
||
|
logger.Errorf("cannot get domain for SSO: %v", err)
|
||
|
fmt.Fprintf(w, "Error: %s\n", errorInternal.Error())
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if d.SsoSecret == "" || d.SsoUrl == "" {
|
||
|
fmt.Fprintf(w, "Error: %s\n", errorMissingConfig.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
key, err := hex.DecodeString(d.SsoSecret)
|
||
|
if err != nil {
|
||
|
logger.Errorf("cannot decode SSO secret as hex: %v", err)
|
||
|
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
h := hmac.New(sha256.New, key)
|
||
|
h.Write(payloadBytes)
|
||
|
expectedSignatureBytes := h.Sum(nil)
|
||
|
if !hmac.Equal(expectedSignatureBytes, signatureBytes) {
|
||
|
fmt.Fprintf(w, "Error: HMAC signature verification failed\n")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
_, err = commenterGetByCommenterToken(payload.Token)
|
||
|
if err != nil && err != errorNoSuchToken {
|
||
|
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
c, err := commenterGetByEmail("sso:"+d.Domain, payload.Email)
|
||
|
if err != nil && err != errorNoSuchCommenter {
|
||
|
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var commenterHex string
|
||
|
|
||
|
// TODO: in case of returning users, update the information we have on record?
|
||
|
if err == errorNoSuchCommenter {
|
||
|
commenterHex, err = commenterNew(payload.Email, payload.Name, payload.Link, payload.Photo, "sso:"+d.Domain, "")
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
||
|
return
|
||
|
}
|
||
|
} else {
|
||
|
commenterHex = c.CommenterHex
|
||
|
}
|
||
|
|
||
|
if err = commenterSessionUpdate(payload.Token, commenterHex); err != nil {
|
||
|
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(w, "<html><script>window.parent.close()</script></html>")
|
||
|
}
|