sso.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. // GenerateSSO - Generate the sso and sig for an sso request
  41. func GenerateSSO(nonce string, returnEndpoint, secret string) (string, string) {
  42. // Build the query string payload
  43. payload := fmt.Sprintf("nonce=%s&return_sso_url=%s", nonce, returnEndpoint)
  44. // Base64 encode the payload
  45. base64Payload := base64.StdEncoding.EncodeToString([]byte(payload))
  46. // Urlencode the
  47. URLEncodedPayload := url.QueryEscape(base64Payload)
  48. // Get a hex signature for this payload with the sso secret
  49. hexSignature := computeHmac256(base64Payload, secret)
  50. return URLEncodedPayload, hexSignature
  51. }
  52. // GetSSOUrl - Generate the sso enpodint url give the domain, sso and sig
  53. func GetSSOUrl(endpoint, sso, sig string) string {
  54. return fmt.Sprintf("%s/session/sso_provider?sso=%s&sig=%s", endpoint, sso, sig)
  55. }
  56. // Create a hex signature from a message and secret
  57. func computeHmac256(message string, secret string) string {
  58. key := []byte(secret)
  59. h := hmac.New(sha256.New, key)
  60. h.Write([]byte(message))
  61. return hex.EncodeToString(h.Sum(nil))
  62. }