sso.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. package discourse
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "encoding/base64"
  6. "encoding/hex"
  7. "fmt"
  8. "net/url"
  9. "github.com/google/uuid"
  10. )
  11. // SsoConfig - Configuration for an SSO Request
  12. type SsoConfig struct {
  13. Endpoint string
  14. ReturnEndpoint string
  15. Secret string
  16. UUID uuid.UUID
  17. }
  18. // GetSSORequestURL - gets a url for an sso request
  19. func GetSSORequestURL(config SsoConfig) string {
  20. url := generateSSORequestURL(config)
  21. return url
  22. }
  23. // ValidateSsoResponse - Validate the signature on the sso response
  24. func ValidateSsoResponse(sso, sig, secret string) bool {
  25. ssoDataSig := computeHmac256(sso, secret)
  26. return sig == ssoDataSig
  27. }
  28. func generateSSORequestURL(config SsoConfig) string {
  29. // Build the query string payload
  30. payload := fmt.Sprintf("nonce=%s&return_sso_url=%s", config.UUID, config.ReturnEndpoint)
  31. // Base64 encode the payload
  32. base64Payload := base64.StdEncoding.EncodeToString([]byte(payload))
  33. // Urlencode the
  34. URLEncodedPayload := url.QueryEscape(base64Payload)
  35. // Get a hex signature for this payload with the sso secret
  36. hexSignature := computeHmac256(base64Payload, config.Secret)
  37. ssoURL := fmt.Sprintf("%s?sso=%s&sig=%s", config.Endpoint, URLEncodedPayload, hexSignature)
  38. return ssoURL
  39. }
  40. // Create a hex signature from a message and secret
  41. func computeHmac256(message string, secret string) string {
  42. key := []byte(secret)
  43. h := hmac.New(sha256.New, key)
  44. h.Write([]byte(message))
  45. return hex.EncodeToString(h.Sum(nil))
  46. }