auth.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. package zllauth1
  2. import (
  3. "crypto/rand"
  4. "encoding/hex"
  5. "encoding/json"
  6. "fmt"
  7. "github.com/dgrijalva/jwt-go"
  8. "github.com/tjfoc/gmsm/sm2"
  9. "time"
  10. )
  11. const zllauthSubject = "zllauth1-auth"
  12. type ZLLAuthHandler struct {
  13. config ZLLAuthConfig
  14. isSecureInit bool
  15. sm2key *sm2.PrivateKey
  16. sm2pubkey string
  17. }
  18. func NewZLLAuthHandler(config ZLLAuthConfig) *ZLLAuthHandler {
  19. o := &ZLLAuthHandler{
  20. config: config,
  21. isSecureInit: false,
  22. }
  23. return o
  24. }
  25. func (h *ZLLAuthHandler) InitSecure() error {
  26. pk, err := sm2.GenerateKey(rand.Reader)
  27. if err != nil {
  28. return err
  29. }
  30. h.sm2key = pk
  31. xenc := hex.EncodeToString(pk.X.Bytes())
  32. yenc := hex.EncodeToString(pk.Y.Bytes())
  33. h.sm2pubkey = SM2PubKeyCombine(xenc, yenc)
  34. h.isSecureInit = true
  35. return nil
  36. }
  37. func (h *ZLLAuthHandler) GetSM2PublicKey() string {
  38. return h.sm2pubkey
  39. }
  40. func (h *ZLLAuthHandler) GetEncryptionInfo() (map[string]string, error) {
  41. if !h.isSecureInit {
  42. return nil, fmt.Errorf("secure module not initialized")
  43. }
  44. return map[string]string{
  45. "method": "sm2",
  46. "pubkey": h.sm2pubkey,
  47. "cipherMode": "C1C3C2",
  48. "header": "04",
  49. }, nil
  50. }
  51. func (h *ZLLAuthHandler) GetJwtTTL() time.Duration {
  52. return h.config.JWTTTL
  53. }
  54. func (h *ZLLAuthHandler) HandlingOtherEncryptedRequest(encData string, v interface{}) (visibleErr LoginFailureType, internalErr error) {
  55. if !h.isSecureInit {
  56. visibleErr = LFT_SECURE_SYSTEM_NOT_INIT
  57. internalErr = fmt.Errorf("secure module not initialized")
  58. return
  59. }
  60. hdec, err := hex.DecodeString(encData)
  61. if err != nil {
  62. visibleErr = LFT_DECODE_HEX_FAIL
  63. internalErr = fmt.Errorf("decode hex data error: %s", err)
  64. return
  65. }
  66. pt, err := sm2.Decrypt(h.sm2key, hdec)
  67. if err != nil {
  68. visibleErr = LFT_DECRYPT_SM2_FAIL
  69. internalErr = fmt.Errorf("decode hex data error: %s", err)
  70. return
  71. }
  72. err = json.Unmarshal(pt, v)
  73. if err != nil {
  74. visibleErr = LFT_UNMARSHAL_JSON_FAIL
  75. internalErr = fmt.Errorf("unmarshal json error: %s", err)
  76. return
  77. }
  78. return LFT_SUCCESS, nil
  79. }
  80. func (h *ZLLAuthHandler) HandlingLogin(data string, serverExternalInfo map[string]interface{}) (isSuccess bool, jwtdata JwtResult, visibleErr LoginFailureType, internalErr error) {
  81. if !h.isSecureInit {
  82. isSuccess = false
  83. jwtdata = NewEmptyJwtResult()
  84. visibleErr = LFT_SECURE_SYSTEM_NOT_INIT
  85. internalErr = fmt.Errorf("secure module not initialized")
  86. return
  87. }
  88. if h.config.UserCheck == nil {
  89. isSuccess = false
  90. jwtdata = NewEmptyJwtResult()
  91. visibleErr = LFT_NO_LOGIN_CHECK_HANDLER
  92. internalErr = fmt.Errorf("no login check handler specified")
  93. return
  94. }
  95. hdec, err := hex.DecodeString(data)
  96. if err != nil {
  97. isSuccess = false
  98. jwtdata = NewEmptyJwtResult()
  99. visibleErr = LFT_DECODE_HEX_FAIL
  100. internalErr = fmt.Errorf("decode hex data error: %s", err)
  101. return
  102. }
  103. pt, err := sm2.Decrypt(h.sm2key, hdec)
  104. if err != nil {
  105. isSuccess = false
  106. jwtdata = NewEmptyJwtResult()
  107. visibleErr = LFT_DECRYPT_SM2_FAIL
  108. internalErr = fmt.Errorf("decode hex data error: %s", err)
  109. return
  110. }
  111. var jdata map[string]interface{}
  112. err = json.Unmarshal(pt, &jdata)
  113. if err != nil {
  114. isSuccess = false
  115. jwtdata = NewEmptyJwtResult()
  116. visibleErr = LFT_UNMARSHAL_JSON_FAIL
  117. internalErr = fmt.Errorf("unmarshal json error: %s", err)
  118. return
  119. }
  120. suc, exi, ve, err := h.config.UserCheck.CheckUserLogin(jdata, serverExternalInfo)
  121. if !suc {
  122. isSuccess = false
  123. jwtdata = NewEmptyJwtResult()
  124. visibleErr = ve
  125. internalErr = fmt.Errorf("error from login check handler: %s", err)
  126. return
  127. }
  128. iat := time.Now().Unix()
  129. exp := time.Now().Add(h.config.JWTTTL).Unix()
  130. clm := &ZLLAuthJwtClaim{
  131. ExpiresAt: exp,
  132. IssuedAt: iat,
  133. Issuer: h.config.JWTIssuer,
  134. NotBefore: iat,
  135. Subject: zllauthSubject,
  136. ExtendInfo: exi,
  137. }
  138. if h.config.JWTJTIGenFunc != nil {
  139. clm.Id = h.config.JWTJTIGenFunc()
  140. }
  141. jsg := jwt.NewWithClaims(h.config.JWTSignMethod, clm)
  142. jr := NewEmptyJwtResult()
  143. jr.ExpireTime = float64(exp)
  144. jr.IssueTime = float64(iat)
  145. tok, err := jsg.SignedString(h.config.JWTPrivateKey)
  146. if err != nil {
  147. isSuccess = false
  148. jwtdata = NewEmptyJwtResult()
  149. visibleErr = LFT_JWT_SIGN_ERROR
  150. internalErr = fmt.Errorf("sign jwt failed: %s", err)
  151. return
  152. }
  153. jr.JwtStr = string(tok)
  154. isSuccess = true
  155. jwtdata = jr
  156. visibleErr = LFT_SUCCESS
  157. internalErr = nil
  158. return
  159. }
  160. func (h *ZLLAuthHandler) parseJwtToClaims(jwtstr string) (clm *ZLLAuthJwtClaim, err error) {
  161. tko, err := jwt.ParseWithClaims(jwtstr, &ZLLAuthJwtClaim{}, func(token *jwt.Token) (i interface{}, err error) {
  162. return h.config.JWTPublicKey, nil
  163. })
  164. if err != nil {
  165. return nil, fmt.Errorf("parse jwt error: %s", err)
  166. }
  167. vcast, castok := tko.Claims.(*ZLLAuthJwtClaim)
  168. if castok {
  169. vok := vcast.VerifyIssuer(h.config.JWTIssuer, true)
  170. if !vok {
  171. return nil, fmt.Errorf("issuer not match")
  172. }
  173. vok = vcast.VerifySubject(zllauthSubject, true)
  174. if !vok {
  175. return nil, fmt.Errorf("subject not match")
  176. }
  177. return vcast, nil
  178. } else {
  179. return nil, fmt.Errorf("claim type not match")
  180. }
  181. }
  182. func (h *ZLLAuthHandler) CheckJWT(jwtstr string) (isSuccess bool, info map[string]interface{}, visibleErr LoginFailureType, internalErr error) {
  183. vclm, err := h.parseJwtToClaims(jwtstr)
  184. if err != nil {
  185. isSuccess = false
  186. info = nil
  187. visibleErr = LFT_JWT_CHECK_FAIL
  188. internalErr = fmt.Errorf("failed check jwt: %s", err)
  189. return
  190. }
  191. if vclm.Issuer != h.config.JWTIssuer {
  192. isSuccess = false
  193. info = nil
  194. visibleErr = LFT_JWT_ISSUER_NOT_MATCH
  195. internalErr = fmt.Errorf("failed check jwt: issuer not match")
  196. return
  197. }
  198. if vclm.Subject != "zllauth1-auth" {
  199. isSuccess = false
  200. info = nil
  201. visibleErr = LFT_JWT_SUBJECT_NOT_MATCH
  202. internalErr = fmt.Errorf("failed check jwt: subject not match")
  203. return
  204. }
  205. isSuccess = true
  206. info = vclm.ExtendInfo
  207. visibleErr = LFT_SUCCESS
  208. internalErr = nil
  209. return
  210. }
  211. func (h *ZLLAuthHandler) RenewJWT(jwtstr string) (isSuccess bool, jwtdata JwtResult, visibleErr LoginFailureType, internalErr error) {
  212. se, exi, ve, err := h.CheckJWT(jwtstr)
  213. if !se {
  214. isSuccess = false
  215. jwtdata = NewEmptyJwtResult()
  216. ve = ve
  217. internalErr = err
  218. return
  219. }
  220. err = h.config.UserCheck.RenewJwtCallback(exi)
  221. if err != nil {
  222. isSuccess = false
  223. jwtdata = NewEmptyJwtResult()
  224. ve = LFT_JWT_RENEW_CALLBACK_ERROR
  225. internalErr = err
  226. return
  227. }
  228. iat := time.Now().Unix()
  229. exp := time.Now().Add(h.config.JWTTTL).Unix()
  230. clm := &ZLLAuthJwtClaim{
  231. ExpiresAt: exp,
  232. IssuedAt: iat,
  233. Issuer: h.config.JWTIssuer,
  234. NotBefore: iat,
  235. Subject: zllauthSubject,
  236. ExtendInfo: exi,
  237. }
  238. if h.config.JWTJTIGenFunc != nil {
  239. clm.Id = h.config.JWTJTIGenFunc()
  240. }
  241. jsg := jwt.NewWithClaims(h.config.JWTSignMethod, clm)
  242. jr := NewEmptyJwtResult()
  243. jr.ExpireTime = float64(exp)
  244. jr.IssueTime = float64(iat)
  245. tok, err := jsg.SignedString(h.config.JWTPrivateKey)
  246. if err != nil {
  247. isSuccess = false
  248. jwtdata = NewEmptyJwtResult()
  249. visibleErr = LFT_JWT_SIGN_ERROR
  250. internalErr = fmt.Errorf("sign jwt failed: %s", err)
  251. return
  252. }
  253. jr.JwtStr = string(tok)
  254. isSuccess = true
  255. jwtdata = jr
  256. visibleErr = LFT_SUCCESS
  257. internalErr = nil
  258. return
  259. }