Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions examples/facebook-auth-example.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
(defpackage oauth2.test.facebook-login
(:use cl oauth2))

(in-package oauth2.test.facebook-login)

(defparameter *app-id* NIL
"Facebook app ID.")

(defparameter *app-secret* NIL
"Facebook app secret")

(defparameter *redirect-uri*
NIL
)

(defparameter *redirect*
(request-code
"https://www.facebook.com/dialog/oauth"
*app-id*
:other `(("redirect_uri" . ,*redirect-uri*))))

(format t "Go to ~A and come back with the code: " *redirect*)
(defparameter *code* (read-line))

(defparameter *token*
(request-token
"https://graph.facebook.com/oauth/access_token"
*code*
:redirect-uri *redirect-uri*
:method :post
:other `(("client_id" . ,*app-id*)
("client_secret" . ,*app-secret*))
:token-parser 'oauth2:facebook-token->alist))

(format t "I got a token:~%~A~%" *token*)
36 changes: 25 additions & 11 deletions oauth2.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
(:export :request-code :request-token :request-resource :refresh-token
:authorization-error :error-code :error-body
:token-string :token-type :token-expires-in
:token-refresh-token :token-scope :token-from-string)
:token-refresh-token :token-scope :token-from-string :facebook-token->alist)
(:documentation
"This package contains a fairly low-level implementation of the OAUTH2 protocol.
It currently only supports \"Authorization Code Grant\" (section 4.1 if the draft)
Expand Down Expand Up @@ -108,7 +108,20 @@ it will be one of the following:
(make-token :string string :type "Bearer"
:expires-in expires-in :refresh-token refresh-token :scope scope))

(defmacro with-handle-token (token)
(defun facebook-token->alist (str)
(list*
(cons :token--type "Bearer")
(loop for i in (ppcre:split "&" str)
collect (let ((data (ppcre:split "=" i)))
(cons
(cond
((string= (car data) "access_token" ) :access--token)
((string= (car data) "expires") :expires--in))
(if (string= (car data) "expires")
(parse-integer (second data))
(second data)))))))

(defmacro with-handle-token (token &optional token-parser)
"Handle the return value you get from a request for a token. Used by request-token and refresh-token."
`(multiple-value-bind (body code) ,token
(case code
Expand All @@ -119,17 +132,17 @@ it will be one of the following:
:uri (assoc1 :error--uri data)
:description (assoc1 :error--description data)))))
(200
(let ((data (parse-json body)))
(let ((data (funcall ,(or token-parser #'parse-json) body)))
(make-token
:string (assoc1 :access--token data)
:type (assoc1 :token--type data)
:expires-in (assoc1 :expires--in data)
:refresh-token (assoc1 :refresh--token data)
:scope (assoc1 :scope data))))
:string (assoc1 :access--token data)
:type (assoc1 :token--type data)
:expires-in (assoc1 :expires--in data)
:refresh-token (assoc1 :refresh--token data)
:scope (assoc1 :scope data))))
(t
(error "Got an invalid response from server. Code: ~A" code)))))

(defun request-token (authorizer code &key redirect-uri (method :get) other)
(defun request-token (authorizer code &key redirect-uri (method :get) other (token-parser 'parse-json))
"Request a token from the authorizer.

CODE has to be authorization code. You can get it from calling REQUEST-CODE.
Expand All @@ -151,7 +164,8 @@ Returns a TOKEN."
(http-request authorizer
:method method
:parameters data
:redirect nil))))
:redirect nil)
token-parser)))

(defun plist-remove (key list)
"Returns a copy of list with the key-value pair identified by KEY removed."
Expand Down Expand Up @@ -195,4 +209,4 @@ The return value is like the one of DRAKMA:HTTP-REQUEST."
(apply
'http-request url :additional-headers
`(("Authorization" . ,(format nil "Bearer ~A" (token-string token))) ,@headers)
other)))
other)))