---
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.
