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…
	
	Add table
		Add a link
		
	
		Reference in a new issue