For some scripts at work I need to log into our Gitlab instance and use its API. To do that you need an OAuth2 token, and I wasn't able to find any examples that I could crib from, so I'm posting what I made. Hopefully this'll help you do the same for your scripts. I should mention that I'm using this with Gitlab as per their instructions, it might be slightly different for other OAuth implementors, but should be roughly the same.

First let's just put the whole script out there before we break it down:

OAUTH_CLIENT="123456789abcdef"
OAUTH_SECRET="123456789abcdef"
PORT=5000

xdg-open "https://gitlab.example.com/oauth/authorize?client_id=${OAUTH_CLIENT}&redirect_uri=http://localhost:${PORT}/&response_type=code" &> /dev/null

OAUTH_CODE=$( echo -e "HTTP/1.1 200 OK\n\n<HTML><body><blink>Thank you</blink></body></HTML>" | nc -l -p ${PORT} | sed -n "s/^GET.*code=\([a-fA-F0-9]*\).*/\1/p" ) 

if [ "${OAUTH_CODE}" == "" ] ; then
    echo "Unable to get OAUTH code"
    exit 1
fi

OAUTH_TOKEN=$(curl -X POST -F "client_id=${OAUTH_CLIENT}" -F "client_secret=${OAUTH_SECRET}" -F "code=${OAUTH_CODE}" -F "grant_type=authorization_code" -F "redirect_uri=http://localhost:5000/" https://gitlab.example.com/oauth/token | jq --raw-output ."access_token" )

if [ "${OAUTH_TOKEN}" == "" ] ; then
    echo "Unable to get OAUTH token"
    exit 1
fi

When you want to use an OAuth2 client with Gitlab the first thing you need to do register as a client, getting the OAUTH_CLIENT and OAUTH_SECRET strings. You'll need to use the first one in the call to open the user's browser.

xdg-open "https://gitlab.example.com/oauth/authorize?client_id=${OAUTH_CLIENT}&redirect_uri=http://localhost:${PORT}/&response_type=code" &> /dev/null

The thing to notice in this call is that we're using localhost for the redirect URL. That means that after (assuming they do) they authenticate the script it will redirect the browser back this host with the code needed to get the token. We then need a webserver running on this machine to get that code.

OAUTH_CODE=$( echo -e "HTTP/1.1 200 OK\n\n<HTML><body><blink>Thank you</blink></body></HTML>" | nc -l -p ${PORT} | sed -n "s/^GET.*code=\([a-fA-F0-9]*\).*/\1/p" ) 

For our webserver we're using the trusty netcat to open a port and give us the data sent there. We go ahead and give the browser a nice webpage to say thanks (you know it's a serious Thank You when you use the <blink> tag). The output you get from netcat is something like this:

GET /?code=123456789abcdef HTTP/1.1
Host: localhost:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1

So we use sed to pull out the code field by replacing the line with just the code and printing it. This gives us the code that we can then turn into a token.

OAUTH_TOKEN=$(curl -X POST -F "client_id=${OAUTH_CLIENT}" -F "client_secret=${OAUTH_SECRET}" -F "code=${OAUTH_CODE}" -F "grant_type=authorization_code" -F "redirect_uri=http://localhost:5000/" https://gitlab.example.com/oauth/token | jq --raw-output ."access_token" )

We set up a rather long curl call with several parameters that results in a JSON object that looks something like:

{
 "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
 "token_type": "bearer",
 "expires_in": 7200,
 "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
}

Which we then use jq to select the access_token and we're good to go. Now we can use that token to access the Gitlab API as we need it.


posted May 8, 2019 | permanent link