-
-
Save scriptjs/2ae3d3de471e0bc8fe8ec2100e50b972 to your computer and use it in GitHub Desktop.
OAuth 2.0 authentication in a Golang CLI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment