#!/usr/local/bin/tclsh # # Usage: # $0 [-q] init|get-auth-code-url # $0 [-q] refresh # # Prerequiste: # ./client-id.dat.tcl # # file to be written: # ./access.json # ./refresh.json # proc usage {} \ { global argv0 puts "Usage:" puts "$argv0 \[-q\] init|get-auth-code-url" puts "$argv0 \[-q\] refresh" puts " -q Quiet mode, just print access-token" exit 1 } set verbose 1 set BINDIR [file dirname $argv0] set VARDIR [file dirname $argv0] set USER_AGENT {mnews-OAuth2-helper/0.0} set LOCALHTTPPORT 8033 # set CLIENT_ID, CLIENT_SECRET source ${BINDIR}/client-id.dat.tcl if [ string equal [lindex $argv 0] "-q" ] { set verbose 0 set argv [lrange $argv 1 end] ;#shift } set quit 0 set authorization_code "" proc ht_accept {fd remoteaddr remoteport} \ { global authorization_code global VARDIR global verbose global quit global argv0 fconfigure $fd -translation auto gets $fd reqline if [regexp {[?&]code=([^&]*)} $reqline {} authorization_code] { set authcode_f [open $VARDIR/authorization_code "w"] puts $authcode_f $authorization_code close $authcode_f if $verbose { puts "authorization_code: $authorization_code" } puts $fd "HTTP/1.0 200 Ok" puts $fd "Content-Type: text/plain" puts $fd "" puts $fd "Got authorization_code: $authorization_code" puts $fd "" puts $fd "Now, go to the oauth2 helper invoking machine, and do \"$argv0 refresh\"." close $fd set quit 1 return } ## force close close $fd } switch -exact -- [lindex $argv 0] { init - get-auth-code-url { ## redirect_uri=urn:ietf:wg:oauth:2.0:oob deprecated as in ## https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html ##puts "https://accounts.google.com/o/oauth2/v2/auth?client_id=${CLIENT_ID}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://mail.google.com/" ## puts "and feed the output to \"${argv0} get-aceess-token 4/...\"" ## ## so, make a simple webserver on localhost:8033 and receive /code=... socket -server ht_accept -myaddr 127.0.0.1 $LOCALHTTPPORT puts "Waiting on http://127.0.0.1:$LOCALHTTPPORT ..." puts "Access to following URL with a recent browser:" puts "https://accounts.google.com/o/oauth2/v2/auth?client_id=${CLIENT_ID}&redirect_uri=http://127.0.0.1:${LOCALHTTPPORT}&response_type=code&scope=https://mail.google.com/" vwait quit if [string length $authorization_code] { if $verbose { puts "Got authorization code: $authorization_code" } } exit 0 } refresh - get-access-token { set refresh_token "" catch { set access_json_f [open $VARDIR/access.json "r"] } {} if ![info exists access_json_f] { #puts stderr "Failed to read $VARDIR/access.json" } else { regexp -line -- {"refresh_token": "([^"]*)"} [read $access_json_f] {} refresh_token close $access_json_f unset access_json_f } if $verbose { puts "refresh token: $refresh_token" } # if ![ string length $refresh_token ] { set authorization_code [read -nonewline [open $VARDIR/authorization_code "r"] ] if ![info exists authorization_code] { puts "Authcode 4/... nonexistent, stop." exit 1 } if ![string length $authorization_code] { puts "Authcode 4/... nonexistent, stop." exit 1 } ## obtain new access token puts stderr "Obtaining new access token, code=$authorization_code ..." exec \ curl --user-agent "$USER_AGENT" \ --data client_id=${CLIENT_ID} \ --data client_secret=${CLIENT_SECRET} \ --data code=$authorization_code \ --data grant_type=authorization_code \ --data redirect_uri=http://127.0.0.1:${LOCALHTTPPORT} \ --silent --insecure \ https://oauth2.googleapis.com/token \ > $VARDIR/access.json.tmp # set aj [open $VARDIR/access.json.tmp "r"] set access_json_content [read $aj] close $aj; unset aj if $verbose { puts -nonewline $access_json_content puts {} } # if [regexp -line -- {"access_token": "([^"]*)"} $access_json_content {} access_token] { if [file exists $VARDIR/access.json ] { file rename -force $VARDIR/access.json $VARDIR/access.json.old } file rename -force $VARDIR/access.json.tmp $VARDIR/access.json if $verbose { puts "New access token:" } puts "$access_token" } else { puts "Failed to get access token." puts "Maybe the authorization code expired;" puts "Access the URL shown by \"$argv0 get-auth-code-url\"." exit 1 } } else { ## obtain new access token from refresh token exec \ curl --user-agent "$USER_AGENT" \ --data client_id=${CLIENT_ID} \ --data client_secret=${CLIENT_SECRET} \ --data grant_type=refresh_token \ --data refresh_token=${refresh_token} \ --silent --insecure \ https://oauth2.googleapis.com/token \ > $VARDIR/refresh.json.tmp set rj [open $VARDIR/refresh.json.tmp "r"] set refresh_json_content [read $rj] close $rj; unset rj if $verbose { puts -nonewline $refresh_json_content puts {} } # if [regexp -line -- {"access_token": "([^"]*)"} $refresh_json_content {} access_token] { if [file exists $VARDIR/refresh.json ] { file rename -force $VARDIR/refresh.json $VARDIR/refresh.json.old } file rename -force $VARDIR/refresh.json.tmp $VARDIR/refresh.json if $verbose { puts "Refreshed access token:" } puts "$access_token" } else { puts "Failed to get access token." puts "Maybe the authorization code expired;" puts "re-access the URL shown by \"$argv0 get-auth-code-url\"." exit 1 } } # #if $verbose && test "$USERID"; then # echo "POP3 AUTH line:" # xoauth2=`printf 'user='"$USERID"'\001auth=Bearer '"$access_token"'\001\001' | openssl base64 | tr -d '\012'` # echo "AUTH XOAUTH2 $xoauth2" #fi # } default { usage exit 1 } } ;#switch