Introducción a OAuth 2.0 y JWT en Swift
Las aplicaciones móviles y de escritorio modernas en Swift (iOS/macOS) utilizan cada vez más el protocolo OAuth 2.0 y el formato JWT (JSON Web Token) para una autorización segura. OAuth 2.0 proporciona acceso delegado a recursos, mientras que JWT permite transmitir datos de usuario de forma compacta y segura. En este artículo, analizaremos cómo implementar una cadena de autorización completa en Swift: desde la obtención del token hasta su verificación y renovación.
Veremos:
- Fundamentos de OAuth 2.0: flujos (flows) y roles
- Estructura de JWT y su decodificación en Swift
- Implementación práctica de autorización usando
URLSession - Almacenamiento de tokens en el llavero (Keychain) y su renovación
Fundamentos de OAuth 2.0 para desarrolladores Swift
OAuth 2.0 es un protocolo de autorización que permite a una aplicación obtener acceso limitado a los recursos de un usuario sin compartir sus credenciales. En el contexto de aplicaciones Swift, el más utilizado es el Authorization Code Flow con PKCE (Proof Key for Code Exchange) para aplicaciones móviles.
Componentes clave de OAuth 2.0
- Resource Owner — el usuario, propietario de los datos
- Client — tu aplicación Swift
- Authorization Server — servidor que emite tokens (por ejemplo, Google, Facebook, tu backend)
- Resource Server — API que proporciona datos protegidos
Un flujo típico en Swift se ve así:
- La aplicación abre una vista web (SFSafariViewController o ASWebAuthenticationSession) para autenticar al usuario.
- Tras un inicio de sesión exitoso, el servidor redirige a una URL de callback con un código temporal.
- La aplicación intercambia el código por un access token y un refresh token.
- El access token se usa para solicitudes a la API, y el refresh token para obtener un nuevo access token cuando expire.
Estructura de JWT y su decodificación en Swift
JWT consta de tres partes separadas por puntos: header.payload.signature. Ejemplo de JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikl2YW4gUGV0cm92IiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cDecodificación del payload en Swift (sin verificar la firma):
import Foundation
struct JWT { static func decodePayload(_ token: String) -> [String: Any]? { let segments = token.components(separatedBy: ".") guard segments.count == 3 else { return nil } var base64 = segments[1] .replacingOccurrences(of: "-", with: "+") .replacingOccurrences(of: "_", with: "/") let length = Double(base64.lengthOfBytes(using: .utf8)) let requiredLength = 4 * ceil(length / 4.0) let padding = Int(requiredLength - length) if padding > 0 { base64 += String(repeating: "=", count: padding) } guard let data = Data(base64Encoded: base64) else { return nil } return try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] }}
// Usoif let payload = JWT.decodePayload("your.jwt.token") { print(payload["sub"] ?? "") print(payload["exp"] ?? "")}Para una verificación completa de la firma JWT en el lado del cliente, usa la librería SwiftJWT o JWTDecode, disponibles a través de Swift Package Manager.
Implementación de OAuth 2.0 y JWT en Swift
Paso 1: Configuración de URLSession y modelos de tokens
struct AuthToken: Codable { let accessToken: String let refreshToken: String? let expiresIn: Int let tokenType: String}
class AuthService { private let session = URLSession.shared