95 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Factor
		
	
	
! Copyright (C) 2016 Björn Lindqvist.
 | 
						|
! See http://factorcode.org/license.txt for BSD license.
 | 
						|
USING: accessors assocs calendar combinators http.client io
 | 
						|
json.reader kernel make math.order sequences unicode urls
 | 
						|
webbrowser ;
 | 
						|
IN: oauth2
 | 
						|
 | 
						|
: console-prompt ( query -- str/f )
 | 
						|
    write flush readln [ blank? ] trim [ f ] when-empty ;
 | 
						|
 | 
						|
: post-json-request ( params token-uri -- assoc )
 | 
						|
    <post-request> dup header>> "application/json" "Accept" rot set-at
 | 
						|
    http-request nip json> ;
 | 
						|
 | 
						|
TUPLE: tokens access refresh expiry ;
 | 
						|
 | 
						|
: assoc>expiry ( json -- expiry )
 | 
						|
    "expires_in" of [ seconds now time+ ] [ f ] if* ;
 | 
						|
 | 
						|
: assoc>tokens ( json -- tokens )
 | 
						|
    [ "access_token" of ]
 | 
						|
    [ "refresh_token" of ]
 | 
						|
    [ assoc>expiry ] tri tokens boa ;
 | 
						|
 | 
						|
: access-expired? ( tokens -- ? )
 | 
						|
    expiry>> [ now before? ] [ f ] if* ;
 | 
						|
 | 
						|
: update-tokens ( tokens1 tokens2 -- tokens1 )
 | 
						|
    2dup expiry>> >>expiry drop access>> >>access ;
 | 
						|
 | 
						|
TUPLE: oauth2
 | 
						|
    auth-uri
 | 
						|
    token-uri
 | 
						|
    redirect-uri
 | 
						|
    client-id
 | 
						|
    client-secret
 | 
						|
    scope
 | 
						|
    extra-params ;
 | 
						|
 | 
						|
: tokens-params ( oauth2 code -- params )
 | 
						|
    [
 | 
						|
        "code" ,,
 | 
						|
        {
 | 
						|
            [ client-id>> "client_id" ,, ]
 | 
						|
            [ client-secret>> "client_secret" ,, ]
 | 
						|
            [ redirect-uri>> "redirect_uri" ,, ]
 | 
						|
            [ extra-params>> %% ]
 | 
						|
        } cleave
 | 
						|
        "authorization_code" "grant_type" ,,
 | 
						|
    ] { } make ;
 | 
						|
 | 
						|
: refresh-params ( oauth2 refresh -- params )
 | 
						|
    [
 | 
						|
        "refresh_token" ,,
 | 
						|
        [ client-id>> "client_id" ,, ]
 | 
						|
        [ client-secret>> "client_secret" ,, ]
 | 
						|
        [ extra-params>> %% ] tri
 | 
						|
        "refresh_token" "grant_type" ,,
 | 
						|
    ] { } make ;
 | 
						|
 | 
						|
: auth-params ( oauth2 -- params )
 | 
						|
    [
 | 
						|
        {
 | 
						|
            [ client-id>> "client_id" ,, ]
 | 
						|
            [ scope>> "scope" ,, ]
 | 
						|
            [ redirect-uri>> "redirect_uri" ,, ]
 | 
						|
            [ extra-params>> %% ]
 | 
						|
        } cleave
 | 
						|
        "code" "response_type" ,,
 | 
						|
        "offline" "access_type" ,,
 | 
						|
    ] { } make ;
 | 
						|
 | 
						|
: oauth2>auth-uri ( oauth2 -- uri )
 | 
						|
    [ auth-uri>> >url ] [ auth-params ] bi set-query-params ;
 | 
						|
 | 
						|
! Other flows can be useful to support too.
 | 
						|
: console-flow ( oauth2 -- tokens/f )
 | 
						|
    dup oauth2>auth-uri open-url
 | 
						|
    "Enter verification code: " console-prompt
 | 
						|
    [
 | 
						|
        dupd tokens-params swap token-uri>> post-json-request
 | 
						|
        assoc>tokens
 | 
						|
    ] [ drop f ] if* ;
 | 
						|
 | 
						|
: refresh-flow ( oauth2 tokens -- tokens' )
 | 
						|
    dupd refresh>> refresh-params swap token-uri>> post-json-request
 | 
						|
    assoc>tokens ;
 | 
						|
 | 
						|
! Using the token to access secured resources.
 | 
						|
: add-token ( request url -- )
 | 
						|
    "Bearer " prepend "Authorization" rot header>> set-at ;
 | 
						|
 | 
						|
: oauth-http-get ( url access-token -- response data )
 | 
						|
    [ <get-request> dup ] dip add-token http-request ;
 |