feat: oauth2_auth_url (pure), oauth2_exchange, oauth2_refresh
Fase 4 del issue 0010 — cliente OAuth2 sin golang.org/x/oauth2. - Oauth2AuthURL es pura: solo construye la URL con net/url - Oauth2Exchange/Refresh hacen POST application/x-www-form-urlencoded - ExpiresAt calculado como now + expires_in del proveedor - Refresh conserva el token original si el proveedor no devuelve uno nuevo - Tests con httptest.NewServer como mock del proveedor
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: oauth2_auth_url
|
||||
kind: function
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func Oauth2AuthURL(config OAuthConfig, state string) string"
|
||||
description: "Construye la URL de autorizacion OAuth2 a partir de la config. Funcion pura que concatena el AuthURL del proveedor con los query params (client_id, redirect_uri, response_type=code, scope, state)."
|
||||
tags: [oauth, oauth2, auth, url, infra]
|
||||
uses_functions: []
|
||||
uses_types: [OAuthConfig_go_infra]
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [net/url, strings]
|
||||
params:
|
||||
- name: config
|
||||
desc: "OAuthConfig del proveedor (Google, GitHub, etc.) con ClientID, AuthURL, RedirectURL y Scopes"
|
||||
- name: state
|
||||
desc: "valor aleatorio anti-CSRF que debe validarse en el callback. Si es vacio no se añade"
|
||||
output: "URL completa a la que redirigir al usuario para iniciar el flujo OAuth2"
|
||||
tested: true
|
||||
tests: ["genera URL con todos los params basicos", "concatena scopes con espacio", "añade state si no es vacio", "detecta si AuthURL ya trae query y usa & en vez de ?"]
|
||||
test_file_path: "functions/infra/oauth2_auth_url_test.go"
|
||||
file_path: "functions/infra/oauth2_auth_url.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
google := OAuthConfig{
|
||||
ClientID: os.Getenv("GOOGLE_CLIENT_ID"),
|
||||
AuthURL: "https://accounts.google.com/o/oauth2/v2/auth",
|
||||
RedirectURL: "http://localhost:8080/callback",
|
||||
Scopes: []string{"openid", "email", "profile"},
|
||||
}
|
||||
state := "random-anti-csrf-token" // guardar en cookie/session
|
||||
url := Oauth2AuthURL(google, state)
|
||||
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Pura — solo hace string building con `net/url.Values.Encode()` (ordena params alfabeticamente y hace URL-encoding). No lee env, ni toca I/O, ni `time.Now()`. El state es critico para prevenir CSRF: debe ser aleatorio por sesion, guardarse server-side (cookie firmada, session, etc.) y validarse en el callback antes de hacer Oauth2Exchange. Un state vacio significa sin proteccion CSRF y no se incluye en la URL — solo apto para pruebas locales.
|
||||
Reference in New Issue
Block a user