Skip to content

Instantly share code, notes, and snippets.

@marians
Created January 27, 2017 10:25
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save marians/3b55318106df0e4e648158f1ffb43d38 to your computer and use it in GitHub Desktop.
Save marians/3b55318106df0e4e648158f1ffb43d38 to your computer and use it in GitHub Desktop.
OAuth 2.0 authentication in a Golang CLI
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"net/http"
"net/url"
"time"
"github.com/fatih/color"
"github.com/skratchdot/open-golang/open"
"golang.org/x/oauth2"
)
var (
conf *oauth2.Config
ctx context.Context
)
func callbackHandler(w http.ResponseWriter, r *http.Request) {
queryParts, _ := url.ParseQuery(r.URL.RawQuery)
// Use the authorization code that is pushed to the redirect
// URL.
code := queryParts["code"][0]
log.Printf("code: %s\n", code)
// Exchange will do the handshake to retrieve the initial access token.
tok, err := conf.Exchange(ctx, code)
if err != nil {
log.Fatal(err)
}
log.Printf("Token: %s", tok)
// The HTTP Client returned by conf.Client will refresh the token as necessary.
client := conf.Client(ctx, tok)
resp, err := client.Get("http://some-server.example.com/")
if err != nil {
log.Fatal(err)
} else {
log.Println(color.CyanString("Authentication successful"))
}
defer resp.Body.Close()
// show succes page
msg := "<p><strong>Success!</strong></p>"
msg = msg + "<p>You are authenticated and can now return to the CLI.</p>"
fmt.Fprintf(w, msg)
}
func main() {
ctx = context.Background()
conf = &oauth2.Config{
ClientID: "cli",
ClientSecret: "",
Scopes: []string{"openid", "profile"},
Endpoint: oauth2.Endpoint{
AuthURL: "https://oauth.example.com/dex/auth",
TokenURL: "https://oauth.example.com/dex/token",
},
// my own callback URL
RedirectURL: "http://127.0.0.1:9999/oauth/callback",
}
// add transport for self-signed certificate to context
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
sslcli := &http.Client{Transport: tr}
ctx = context.WithValue(ctx, oauth2.HTTPClient, sslcli)
// Redirect user to consent page to ask for permission
// for the scopes specified above.
url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline)
log.Println(color.CyanString("You will now be taken to your browser for authentication"))
time.Sleep(1 * time.Second)
open.Run(url)
time.Sleep(1 * time.Second)
log.Printf("Authentication URL: %s\n", url)
http.HandleFunc("/oauth/callback", callbackHandler)
log.Fatal(http.ListenAndServe(":9999", nil))
}
@nmrshll
Copy link

nmrshll commented Jun 24, 2017

you made my day yesterday ! 👍 Thank you
I turned your gist into a small library at https://github.com/n-marshall/oauth2-noserver

@aquiseb
Copy link

aquiseb commented May 20, 2018

You made my day too, thanks

@chriskolenko
Copy link

You didn't make my day. Your state value is bad.

@cameronbrill
Copy link

You made my day!

@varsubham
Copy link

you made my day too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment