Help me bij het implementeren van OAuth2 authenticatie in mijn Go applicatie
description
Het gebruik van OAuth2 verbetert de beveiliging van je applicatie door gebruikersauthenticatie en autorisatie effectief te beheren, wat zorgt voor veiligere interacties met externe diensten.
prompt
try_prompt
Help me OAuth2 authenticatie op te zetten in mijn Go applicatie. Leg uit hoe je de OAuth2 provider configureert, tokens genereert en valideert ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een stapsgewijze handleiding om OAuth2-authenticatie met Google in je Go-applicatie op te zetten, inclusief voorbeeldcode.
---
### 1. OAuth2 Provider configureren (Google)
#### a. Google API Console setup
1. Ga naar [Google Cloud Console](https://console.developers.google.com/).
2. Maak een nieuw project of selecteer een bestaand project.
3. Ga naar **Credentials**.
4. Klik op **Create Credentials** > **OAuth 2.0 Client IDs**.
5. Kies **Application Type**: bijvoorbeeld **Web application**.
6. Voeg de **Authorized redirect URIs** toe (bijvoorbeeld: `http://localhost:8080/auth/callback`).
7. Download de `client_secret.json` of noteer de client ID en secret.
---
### 2. OAuth2 in Go integreren
Gebruik de officiële `golang.org/x/oauth2` package en de Google provider.
#### a. Dependencies installeren
```bash
go get golang.org/x/oauth2
go get golang.org/x/oauth2/google
```
#### b. OAuth2 configuratie code voorbeeld
```go
package main
import (
"context"
"fmt"
"log"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
var (
// Vervang deze waarden door jouw client ID en secret
oauth2Config = &oauth2.Config{
ClientID: "JOUW_CLIENT_ID",
ClientSecret: "JOUW_CLIENT_SECRET",
RedirectURL: "http://localhost:8080/auth/callback",
Scopes: []string{"openid", "profile", "email"},
Endpoint: google.Endpoint,
}
// In-memory sessies (voor demo), gebruik een database in productie
stateToken = "randomstate" // genereer een veilige unieke waarde
)
func main() {
http.HandleFunc("/", handleMain)
http.HandleFunc("/login", handleLogin)
http.HandleFunc("/auth/callback", handleCallback)
fmt.Println("Server gestart op http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleMain(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `<a href="/login">Login met Google</a>`)
}
func handleLogin(w http.ResponseWriter, r *http.Request) {
url := oauth2Config.AuthCodeURL(stateToken, oauth2.AccessTypeOffline)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
func handleCallback(w http.ResponseWriter, r *http.Request) {
if r.FormValue("state") != stateToken {
http.Error(w, "Ongeldige state parameter", http.StatusBadRequest)
return
}
code := r.FormValue("code")
token, err := oauth2Config.Exchange(context.Background(), code)
if err != nil {
http.Error(w, "Token verwerving mislukt", http.StatusInternalServerError)
return
}
// Token opslaan en gebruiker authentiseren
client := oauth2Config.Client(context.Background(), token)
// Haal gebruikersinfo op
resp, err := client.Get("https://www.googleapis.com/oauth2/v3/userinfo")
if err != nil {
http.Error(w, "Fout bij ophalen gebruikersinfo", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
// Lees en toon gebruikersinfo
// Hier kun je JSON decoderen en gebruiken
var userInfo map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil {
http.Error(w, "Fout bij decoderen gebruikersinfo", http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Gebruiker info: %+v", userInfo)
}
```
---
### 3. Tokens genereren en valideren
- **Tokens genereren:** gebeurt automatisch bij `oauth2Config.Exchange()`.
- **Tokens valideren:** bevestig dat de access token geldig is door API-aanroepen te doen met de token. Google biedt ook ID tokens (JWT) die je kunt verifieren met de publieke keys van Google.
Voor eenvoudige verificatie kun je het access token gebruiken zoals in het voorbeeld. Voor meer veiligheid, valideer de ID token (JWT) met de juiste libraries.
---
### 4. Eindpunten beveiligen
- Controleer of de gebruiker ingelogd is voordat je bepaalde routes toelaat.
- Bewaar de tokens in sessies of cookies.
- Bij elke beveiligde route, check of de gebruiker een geldig token heeft.
Voorbeeld:
```go
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Hier haal je token uit sessie/cookie
// en valideer je deze
// Als niet geldig: redirect naar login
// Voor demo: ga door
next.ServeHTTP(w, r)
})
}
```
---
### Samenvatting
- Configureer Google OAuth2 credentials.
- Implementeer login en callback endpoints.
- Gebruik `oauth2.Config` voor tokenaanvragen.
- Haal gebruikersinfo op met de access token.
- Beveilig je endpoints door authenticatie te controleren.
---
Wil je dat ik je help met een complete, werkende demo of meer details over tokenverificatie en sessiebeheer?
provider: deepseek
model: deepseek-chat
Ik help je graag met het opzetten van OAuth2 authenticatie met Google in je Go applicatie. Hier is een complete uitleg met voorbeeldcode.
## 1. Vereisten en installatie
Installeer eerst de benodigde packages:
```bash
go get golang.org/x/oauth2
go get golang.org/x/oauth2/google
```
## 2. OAuth2 configuratie
```go
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
// OAuth2 configuratie voor Google
var googleOauthConfig = &oauth2.Config{
RedirectURL: "http://localhost:8080/auth/google/callback",
ClientID: "je-google-client-id",
ClientSecret: "je-google-client-secret",
Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},
Endpoint: google.Endpoint,
}
// Willekeurige staat voor beveiliging (in productie gebruik een cryptografisch veilige waarde)
var oauthStateString = "random-state-string"
```
## 3. Google OAuth2 instellen
1. Ga naar [Google Cloud Console](https://console.cloud.google.com/)
2. Maak een nieuw project of selecteer een bestaand project
3. Ga naar "APIs & Services" > "Credentials"
4. Maak een OAuth 2.0 Client ID aan
5. Configureer geautoriseerde redirect URIs (bijv. `http://localhost:8080/auth/google/callback`)
## 4. Authenticatie endpoints
```go
// Start OAuth2 flow
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
url := googleOauthConfig.AuthCodeURL(oauthStateString)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
// Callback handler voor Google OAuth2
func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
state := r.FormValue("state")
if state != oauthStateString {
http.Error(w, "Ongeldige staat parameter", http.StatusBadRequest)
return
}
code := r.FormValue("code")
token, err := googleOauthConfig.Exchange(context.Background(), code)
if err != nil {
http.Error(w, "Kon token niet uitwisselen: "+err.Error(), http.StatusInternalServerError)
return
}
// Valideer token en haal gebruikersinformatie op
userInfo, err := getUserInfo(token)
if err != nil {
http.Error(w, "Kon gebruikersinformatie niet ophalen: "+err.Error(), http.StatusInternalServerError)
return
}
// Sla token op (in productie gebruik een veilige opslag)
// Bijvoorbeeld in een cookie of session
http.SetCookie(w, &http.Cookie{
Name: "oauth_token",
Value: token.AccessToken,
Path: "/",
HttpOnly: true,
Secure: false, // Zet op true in productie met HTTPS
})
fmt.Fprintf(w, "Ingelogd als: %s", userInfo.Email)
}
// Haal gebruikersinformatie op van Google
func getUserInfo(token *oauth2.Token) (*GoogleUserInfo, error) {
client := googleOauthConfig.Client(context.Background(), token)
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
return nil, err
}
defer resp.Body.Close()
var userInfo GoogleUserInfo
err = json.NewDecoder(resp.Body).Decode(&userInfo)
if err != nil {
return nil, err
}
return &userInfo, nil
}
// Google gebruikersinformatie struct
type GoogleUserInfo struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
Picture string `json:"picture"`
}
```
## 5. Token validatie middleware
```go
// Middleware om endpoints te beveiligen
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Haal token op uit cookie
cookie, err := r.Cookie("oauth_token")
if err != nil {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
// Valideer token (eenvoudige validatie - in productie uitgebreider)
token := &oauth2.Token{AccessToken: cookie.Value}
client := googleOauthConfig.Client(context.Background(), token)
// Test of token nog geldig is door een eenvoudige API call
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil || resp.StatusCode != http.StatusOK {
// Token is ongeldig, redirect naar login
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
resp.Body.Close()
// Token is geldig, ga door naar volgende handler
next.ServeHTTP(w, r)
}
}
// Uitgebreide token validatie functie
func validateToken(accessToken string) (bool, *GoogleUserInfo, error) {
token := &oauth2.Token{AccessToken: accessToken}
client := googleOauthConfig.Client(context.Background(), token)
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
return false, nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return false, nil, nil
}
var userInfo GoogleUserInfo
err = json.NewDecoder(resp.Body).Decode(&userInfo)
if err != nil {
return false, nil, err
}
return true, &userInfo, nil
}
```
## 6. Complete applicatie integratie
```go
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func main() {
// Haal credentials op uit environment variables (veiliger)
googleOauthConfig.ClientID = os.Getenv("GOOGLE_CLIENT_ID")
googleOauthConfig.ClientSecret = os.Getenv("GOOGLE_CLIENT_SECRET")
if googleOauthConfig.ClientID == "" || googleOauthConfig.ClientSecret == "" {
log.Fatal("GOOGLE_CLIENT_ID en GOOGLE_CLIENT_SECRET moeten zijn ingesteld")
}
// Routes
http.HandleFunc("/", homeHandler)
http.HandleFunc("/login", handleGoogleLogin)
http.HandleFunc("/auth/google/callback", handleGoogleCallback)
http.HandleFunc("/protected", authMiddleware(protectedHandler))
http.HandleFunc("/logout", logoutHandler)
fmt.Println("Server draait op http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `
<h1>Welkom bij de OAuth2 Demo</h1>
<a href="/login">Inloggen met Google</a>
`)
}
func protectedHandler(w http.ResponseWriter, r *http.Request) {
// Haal gebruikersinformatie op voor weergave
cookie, _ := r.Cookie("oauth_token")
isValid, userInfo, _ := validateToken(cookie.Value)
if isValid && userInfo != nil {
fmt.Fprintf(w, `
<h1>Beveiligd gebied</h1>
<p>Welkom, %s!</p>
<p>Email: %s</p>
<img src="%s" alt="Profiel foto" width="50">
<br><br>
<a href="/logout">Uitloggen</a>
`, userInfo.Name, userInfo.Email, userInfo.Picture)
} else {
http.Error(w, "Ongeldige sessie", http.StatusUnauthorized)
}
}
func logoutHandler(w http.ResponseWriter, r *http.Request) {
// Verwijder cookie
http.SetCookie(w, &http.Cookie{
Name: "oauth_token",
Value: "",
Path: "/",
MaxAge: -1,
})
http.Redirect(w, r, "/", http.StatusSeeOther)
}
```
## 7. Environment variables configuratie
Maak een `.env` bestand of stel environment variables in:
```bash
export GOOGLE_CLIENT_ID="je-client-id.apps.googleusercontent.com"
export GOOGLE_CLIENT_SECRET="je-client-secret"
```
## 8. Beveiligingsoverwegingen
1. **State parameter**: Gebruik altijd een cryptografisch veilige state parameter
2. **HTTPS**: Gebruik altijd HTTPS in productie
3. **Token opslag**: Sla tokens veilig op (httpOnly cookies)
4. **Token refresh**: Implementeer token refresh logica
5. **CSRF bescherming**: Voeg CSRF tokens toe aan formulieren
## 9. Uitgebreide token validatie
```go
// Verbeterde token validatie met refresh
func validateAndRefreshToken(accessToken string, refreshToken string) (string, error) {
token := &oauth2.Token{
AccessToken: accessToken,
RefreshToken: refreshToken,
}
// Maak een token source die automatisch refresh
tokenSource := googleOauthConfig.TokenSource(context.Background(), token)
newToken, err := tokenSource.Token()
if err != nil {
return "", err
}
return newToken.AccessToken, nil
}
```
Deze implementatie biedt een complete OAuth2 integratie met Google in je Go applicatie. Vergeet niet om de client ID en secret te vervangen door je eigen credentials van Google Cloud Console.

