PageRenderTime 34ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/core/tokens.lisp

http://github.com/skypher/cl-oauth
Lisp | 137 lines | 100 code | 23 blank | 14 comment | 5 complexity | 7f29ce260275e75823387a86a6b4e0a9 MD5 | raw file
Possible License(s): LGPL-3.0
  1. (in-package :oauth)
  2. ;;; section 6.
  3. ;;;
  4. ;;; OAuth Authentication is done in three steps:
  5. ;;;
  6. ;;; 1. The Consumer obtains an unauthorized Request Token.
  7. ;;; 2. The User authorizes the Request Token.
  8. ;;; 3. The Consumer exchanges the Request Token for an Access Token.
  9. ;;;
  10. ;;; TODO: token registry GC
  11. ;;; default token values
  12. (let ((random-state (make-random-state t)))
  13. (defun random-key ()
  14. (format nil "~36,25,'0r" (random (expt 36 25) random-state)))
  15. (defun random-secret ()
  16. (format nil "~36,25,'0r" (random (expt 36 25) random-state)))
  17. (defun random-verification-code ()
  18. (format nil "~36,25,'0r" (random (expt 36 25) random-state))))
  19. ;;; token base class
  20. (defclass token ()
  21. ((key :type string
  22. :reader token-key
  23. :initarg :key
  24. :initform (random-key))
  25. (secret :type string
  26. :reader token-secret
  27. :initarg :secret
  28. :initform (random-secret))
  29. (user-data :type list
  30. :accessor token-user-data
  31. :initarg :user-data
  32. :initform nil
  33. :documentation "Application-specific data associated
  34. with this token; an alist.")))
  35. (defmethod print-object ((obj token) stream)
  36. "Faking STRUCT-like output. It would probably be better to use
  37. the pretty printer; the code for sb-kernel::%default-structure-pretty-print
  38. will be a useful template."
  39. (print-unreadable-object (obj stream :type t :identity (not *print-pretty*))
  40. (loop for slotname in (mapcar #'c2mop:slot-definition-name
  41. (c2mop:class-slots (class-of obj)))
  42. do (progn
  43. (terpri stream)
  44. (write " " :stream stream :escape nil)
  45. (prin1 (intern (symbol-name slotname) :keyword) stream)
  46. (write " " :stream stream :escape nil)
  47. (prin1 (if (slot-boundp obj slotname)
  48. (slot-value obj slotname)
  49. "(unbound)")
  50. stream)))))
  51. ;;; consumer tokens
  52. (defclass consumer-token (token)
  53. ((last-timestamp :type integer
  54. :accessor consumer-token-last-timestamp
  55. :initform 0)))
  56. (defun make-consumer-token (&rest args)
  57. (apply #'make-instance 'consumer-token args))
  58. (defclass consumer-ref-mixin ()
  59. ((consumer :type consumer-token
  60. :accessor token-consumer
  61. :initarg :consumer
  62. :documentation "The Consumer that originally requested this
  63. token."))
  64. (:documentation "Mixin for classes that refer to a consumer."))
  65. ;;; request tokens
  66. (defclass request-token (token consumer-ref-mixin)
  67. ((callback-uri :type (or puri:uri null)
  68. :reader request-token-callback-uri
  69. :initarg :callback-uri
  70. :initform nil
  71. :documentation "Callback URI for this request token.
  72. NIL means oob.")
  73. (verification-code :type (or string null)
  74. :accessor request-token-verification-code
  75. :initarg :verification-code
  76. :initform (random-verification-code)
  77. :documentation "Might be NIL for OAuth 1.0")
  78. (authorized-p :type boolean
  79. :accessor request-token-authorized-p
  80. :initform nil)))
  81. (defun make-request-token (&rest args)
  82. (apply #'make-instance 'request-token args))
  83. ;;; access tokens
  84. (defclass access-token (token consumer-ref-mixin)
  85. ((session-handle :type (or string null)
  86. :reader access-token-session-handle
  87. :initarg :session-handle
  88. :initform nil)
  89. (expires :type (or integer null)
  90. :reader access-token-expires
  91. :initarg :expires
  92. :initform nil
  93. :documentation "Universal time when this token expires.")
  94. (authorization-expires
  95. :type (or integer null)
  96. :reader access-token-authorization-expires
  97. :initarg :authorization-expires
  98. :initform nil
  99. :documentation "Universal time when this token's session expires.")
  100. (origin-uri
  101. :type (or puri:uri string null)
  102. :reader access-token-origin-uri
  103. :initarg :origin-uri
  104. :initform nil
  105. :documentation "URI this access token has been obtained from.
  106. Needed for refresh.")))
  107. (defun make-access-token (&rest args)
  108. (apply #'make-instance 'access-token args))
  109. (defun access-token-expired-p (access-token)
  110. (and (access-token-session-handle access-token)
  111. (or (aand (access-token-expires access-token)
  112. (> (get-universal-time) it))
  113. (aand (access-token-authorization-expires access-token)
  114. (> (get-universal-time) it)))))