Publish HTML quickly. https://html.house
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

102 lines
2.1 KiB

  1. package htmlhouse
  2. import (
  3. "fmt"
  4. jwt "github.com/dgrijalva/jwt-go"
  5. "github.com/juju/errgo"
  6. "io/ioutil"
  7. "net/http"
  8. )
  9. const (
  10. tokenHeader = "Authorization"
  11. )
  12. type sessionManager interface {
  13. readToken(*http.Request) (string, error)
  14. createToken(string) (string, error)
  15. writeToken(http.ResponseWriter, string) error
  16. }
  17. // Basic user session info
  18. type sessionInfo struct {
  19. ID string `json:"id"`
  20. }
  21. func newSessionInfo(houseID string) *sessionInfo {
  22. return &sessionInfo{houseID}
  23. }
  24. func newSessionManager(cfg *config) (sessionManager, error) {
  25. mgr := &defaultSessionManager{}
  26. var err error
  27. mgr.signKey, err = ioutil.ReadFile(cfg.PrivateKey)
  28. if err != nil {
  29. return mgr, errgo.Mask(err)
  30. }
  31. mgr.verifyKey, err = ioutil.ReadFile(cfg.PublicKey)
  32. if err != nil {
  33. return mgr, errgo.Mask(err)
  34. }
  35. return mgr, nil
  36. }
  37. type defaultSessionManager struct {
  38. verifyKey, signKey []byte
  39. }
  40. func (m *defaultSessionManager) readToken(r *http.Request) (string, error) {
  41. tokenString := r.Header.Get(tokenHeader)
  42. if tokenString == "" {
  43. return "", nil
  44. }
  45. token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
  46. if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
  47. return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
  48. }
  49. return m.verifyKey, nil
  50. })
  51. switch err.(type) {
  52. case nil:
  53. if !token.Valid {
  54. return "", nil
  55. }
  56. claims := token.Claims.(jwt.MapClaims)
  57. houseID := claims["houseID"].(string)
  58. return houseID, nil
  59. case *jwt.ValidationError:
  60. return "", nil
  61. default:
  62. return "", errgo.Mask(err)
  63. }
  64. }
  65. func (m *defaultSessionManager) createToken(houseID string) (string, error) {
  66. token := jwt.New(jwt.SigningMethodRS512)
  67. claims := token.Claims.(jwt.MapClaims)
  68. claims["houseID"] = houseID
  69. tokenString, err := token.SignedString(m.signKey)
  70. if err != nil {
  71. return tokenString, errgo.Mask(err)
  72. }
  73. return tokenString, nil
  74. }
  75. func (m *defaultSessionManager) writeToken(w http.ResponseWriter, houseID string) error {
  76. tokenString, err := m.createToken(houseID)
  77. if err != nil {
  78. return err
  79. }
  80. w.Header().Set(tokenHeader, tokenString)
  81. return nil
  82. }