Begin supporting Monzo OAuth 2.0 login flow
What's done: - Basic support of the client authorization grant stage of the OAuth login flow: - Open Google Chrome to point the user to Monzo's client authorization page. - Created a web server to retrieve the authorization code from Monzo. What's left: - Pulling the authorization grant (i.e. code) from Monzo's request and exchanging it for an access token and a refresh token, which can be used to make subsequent requests. Unanswered question: - Assuming this is a stateless app, where should I store the access token and refresh token to avoid the authorization flow. I'd like to avoid the client authorization flow because ideally I could run this app as a job that runs periodically throughout the day without requiring my interactions with it. Some interesting notes: - Notice how in the .envrc file, it's possible to make calls to `pass`. This allows me to check in the .envrc files without obscuring their content. It also allows me to consume these values in my app by using `os.Getenv("client_secret")`, which I find straightforward. Overall, I'm quite pleased to have stumbled upon this pattern - assuming that it's secure.
This commit is contained in:
parent
cce926d60f
commit
70034d4cb9
2 changed files with 43 additions and 0 deletions
2
monzo-ynab/.envrc
Normal file
2
monzo-ynab/.envrc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export client_id="$(pass show finance/monzo/client-id)"
|
||||||
|
export client_secret="$(pass show finance/monzo/client-secret)"
|
41
monzo-ynab/main.go
Normal file
41
monzo-ynab/main.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Creating a job to import Monzo transactions into YNAB.
|
||||||
|
//
|
||||||
|
// This is going to run N times per 24 hours.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
clientId = os.Getenv("client_id")
|
||||||
|
clientSecret = os.Getenv("client_secret")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
state = "xyz123"
|
||||||
|
redirectUri = "http://localhost:8080/authorize"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleRedirect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Println(r)
|
||||||
|
fmt.Fprintf(w, "Ackified")
|
||||||
|
}
|
||||||
|
|
||||||
|
func authorizeClient() {
|
||||||
|
url :=
|
||||||
|
fmt.Sprintf("https://auth.monzo.com/?client_id=%s&redirect_uri=%s&response_type=code&state=:state",
|
||||||
|
clientId, redirectUri, state)
|
||||||
|
exec.Command("google-chrome", url).Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
authorizeClient()
|
||||||
|
http.HandleFunc("/authorize", handleRedirect)
|
||||||
|
go log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
|
}
|
Loading…
Reference in a new issue