# Catatan Seekor Oauth

> <� **Quick Start**: Panduan lengkap implementasi OAuth 2.0 dan OpenID Connect untuk secure authentication dan authorization dalam aplikasi modern.

## =� Daftar Isi

* [<� Overview](#-overview)
* [= OAuth 2.0 Fundamentals](#-oauth-20-fundamentals)
* [= Grant Types](#-grant-types)
* [<� OpenID Connect (OIDC)](#-openid-connect-oidc)
* \[=� Implementation]\(#-implementation)
* [=' Security Best Practices](#-security-best-practices)
* [=� Common Vulnerabilities](#-common-vulnerabilities)
* [=� Testing & Validation](#-testing--validation)
* [= Integration Examples](#-integration-examples)
* [=� Resources](#-resources)

## <� Overview

OAuth 2.0 adalah authorization framework yang memungkinkan third-party applications untuk mendapatkan akses terbatas ke user accounts pada layanan HTTP, melalui proses authorization yang user-approved. OpenID Connect (OIDC) adalah extension dari OAuth 2.0 yang menambahkan authentication layer.

### < **Mengapa OAuth/OIDC?**

* **= Secure Delegation**: User dapat memberikan akses tanpa sharing credentials
* **<� Fine-Grained Access**: Kontrol yang presisi atas resource yang dapat diakses
* **= Token-Based**: Stateless authentication dengan access tokens
* **< Standard Protocol**: Industry standard yang didukung secara luas
* **=� Cross-Platform**: Works untuk web, mobile, dan desktop applications

## = OAuth 2.0 Fundamentals

### <� **Core Concepts**

```yaml
Actors:
  Resource Owner: User yang memiliki data
  Client: Application yang meminta akses
  Authorization Server: Server yang mengeluarkan tokens
  Resource Server: Server yang host protected resources

Tokens:
  Access Token: Credential untuk mengakses resources
  Refresh Token: Credential untuk mendapatkan access token baru
  ID Token: JWT yang berisi user info (OIDC)
```

### = **OAuth 2.0 Flow**

```
1. Authorization Request
   Client � Authorization Server: "I need permission to access user data"

2. User Authentication & Consent
   Authorization Server � User: "Do you authorize this application?"

3. Authorization Grant
   Authorization Server � Client: "User approved, here's authorization code"

4. Token Exchange
   Client � Authorization Server: "Exchange code for access token"

5. Access Resource
   Client � Resource Server: "Access user data with access token"
```

### =� **Token Structure**

```json
{
  "access_token": "eyJz93a...k4laUWw",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "scope": "read write",
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6..."
}
```

## = Grant Types

### = **Authorization Code Flow (Recommended)**

```yaml
Use Case: Web applications with server-side backend
Security: High (tokens never exposed to browser)
PKCE Support: Yes (required for SPAs)

Flow:
  1. Redirect user to authorization server
  2. User authenticates and consents
  3. Receive authorization code
  4. Exchange code for tokens (server-side)
```

**Implementation Example:**

```javascript
// Frontend: Authorization Request
const authUrl = 'https://auth.example.com/authorize?' +
  'response_type=code&' +
  'client_id=your_client_id&' +
  'redirect_uri=https://yourapp.com/callback&' +
  'scope=read write&' +
  'state=random_string&' +
  'code_challenge=generated_challenge&' +
  'code_challenge_method=S256';

window.location.href = authUrl;

// Backend: Token Exchange
const tokenResponse = await fetch('https://auth.example.com/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: 'your_client_id',
    client_secret: 'your_client_secret',
    redirect_uri: 'https://yourapp.com/callback',
    code_verifier: storedVerifier
  })
});
```

### =� **Client Credentials Flow**

```yaml
Use Case: Machine-to-Machine (M2M) authentication
Security: High (no user interaction)
Scope: Application-level permissions

Flow:
  1. Client authenticates with client credentials
  2. Receive access token directly
  3. Use token to access resources
```

**Implementation Example:**

```javascript
const tokenResponse = await fetch('https://auth.example.com/token', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic ' + btoa('client_id:client_secret'),
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: 'grant_type=client_credentials&scope=read write'
});
```

### =d **Resource Owner Password Credentials Flow**

```yaml
Use Case: First-party applications (high trust)
Security: Medium (credentials handled by client)
Warning: Not recommended for third-party apps

Flow:
  1. User provides credentials to client
  2. Client exchanges credentials for tokens
  3. Use tokens for resource access
```

### =� **Implicit Flow (Deprecated)**

```yaml
Status: Deprecated - Use Authorization Code + PKCE instead
Security Issues: Tokens exposed in URL
Alternative: Authorization Code Flow with PKCE
```

## <� OpenID Connect (OIDC)

### <� **OIDC vs OAuth 2.0**

```yaml
OAuth 2.0: Authorization framework
OpenID Connect: Authentication layer + OAuth 2.0

Key Features:
  - ID Token with user claims
  - UserInfo endpoint
  - Discovery document
  - Dynamic client registration
```

### =

**ID Token Structure**

```json
{
  "header": {
    "alg": "RS256",
    "typ": "JWT",
    "kid": "key_id"
  },
  "payload": {
    "iss": "https://auth.example.com",
    "sub": "user_id_123",
    "aud": "client_id",
    "exp": 1640995200,
    "iat": 1640991600,
    "email": "user@example.com",
    "name": "John Doe",
    "picture": "https://example.com/avatar.jpg"
  }
}
```

### =

**OIDC Endpoints**

```yaml
Discovery: https://auth.example.com/.well-known/openid-configuration

Key Endpoints:
  - authorization_endpoint
  - token_endpoint
  - userinfo_endpoint
  - jwks_uri
  - end_session_endpoint
```

## =� Implementation

### <� **Server-Side Implementation (Node.js)**

```javascript
const express = require('express');
const { auth, requiresAuth } = require('express-openid-connect');

const config = {
  authRequired: false,
  auth0Logout: true,
  secret: 'a-long-random-string',
  baseURL: 'http://localhost:3000',
  clientID: 'your_client_id',
  issuerBaseURL: 'https://your-tenant.auth0.com'
};

app.use(auth(config);

// Protected route
app.get('/profile', requiresAuth(), (req, res) => {
  res.send(JSON.stringify(req.oidc.user));
});

// Authentication callback
app.get('/auth/callback', (req, res) => {
  res.redirect('/profile');
});
```

### <� **Client-Side Implementation (React)**

```javascript
import { Auth0Provider, useAuth0 } from '@auth0/auth0-react';

function App() {
  return (
    <Auth0Provider
      domain="your-tenant.auth0.com"
      clientId="your_client_id"
      redirectUri={window.location.origin}>
      <ProtectedRoute component={Dashboard} path="/dashboard" />
    </Auth0Provider>
  );
}

function useAuth() {
  const {
    isAuthenticated,
    user,
    loginWithRedirect,
    logout
  } = useAuth0();

  return {
    isAuthenticated,
    user,
    login: () => loginWithRedirect(),
    logout: () => logout({ returnTo: window.location.origin })
  };
}
```

### =

**Python Implementation (FastAPI)**

```python
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2AuthorizationCodeBearer
import httpx

app = FastAPI()

oauth2_scheme = OAuth2AuthorizationCodeBearer(
    authorizationUrl="https://auth.example.com/authorize",
    tokenUrl="https://auth.example.com/token"
)

async def get_current_user(token: str = Depends(oauth2_scheme)):
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://auth.example.com/userinfo",
            headers={"Authorization": f"Bearer {token}"}
        )

    if response.status_code != 200:
        raise HTTPException(status_code=401, detail="Invalid token")

    return response.json()

@app.get("/profile")
async def profile(current_user: dict = Depends(get_current_user)):
    return current_user
```

## =' Security Best Practices

### =� **State Management**

```javascript
// Generate cryptographically random state
function generateState() {
  const array = new Uint32Array(10);
  crypto.getRandomValues(array);
  return Array.from(array, dec => ('0' + dec.toString(16)).substr(-2)).join('');
}

// Store state in session
sessionStorage.setItem('oauth_state', generatedState);

// Verify state on callback
const returnedState = new URLSearchParams(window.location.search).get('state');
const storedState = sessionStorage.getItem('oauth_state');

if (returnedState !== storedState) {
  throw new Error('Invalid state - CSRF attack detected');
}
```

### = **PKCE (Proof Key for Code Exchange)**

```javascript
// Generate PKCE verifier and challenge
async function generatePKCE() {
  const verifier = generateRandomString(128);
  const encoder = new TextEncoder();
  const data = encoder.encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);

  const challenge = btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');

  return { verifier, challenge };
}

// Store verifier for token exchange
sessionStorage.setItem('pkce_verifier', verifier);
```

### = **Token Storage**

```yaml
Recommended Storage:
  Access Token: Memory or sessionStorage
  Refresh Token: Secure, HttpOnly cookie
  ID Token: Memory (parse once)

Avoid:
  - LocalStorage for sensitive tokens
  - URL parameters for tokens
  - Unsecured cookie transmission
```

### =� **Token Validation**

```javascript
// Validate JWT token structure
function validateIDToken(token) {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) {
      throw new Error('Invalid JWT structure');
    }

    const header = JSON.parse(atob(parts[0]));
    const payload = JSON.parse(atob(parts[1]));

    // Verify required claims
    if (!payload.iss || !payload.sub || !payload.aud || !payload.exp) {
      throw new Error('Missing required claims');
    }

    // Verify expiration
    if (Date.now() >= payload.exp * 1000) {
      throw new Error('Token expired');
    }

    return { header, payload };
  } catch (error) {
    console.error('Token validation failed:', error);
    return null;
  }
}
```

## =� Common Vulnerabilities

### =

**1. Authorization Code Interception**

```yaml
Vulnerability: Attacker intercepts authorization code
Mitigation: Use PKCE (Proof Key for Code Exchange)
Impact: Prevents code injection attacks
```

### =

**2. CSRF Attacks**

```yaml
Vulnerability: Cross-site request forgery
Mitigation: Use state parameter with random values
Impact: Prevents unauthorized authorization
```

### =

**3. Token Leakage**

```yaml
Vulnerability: Tokens exposed in URLs or logs
Mitigation: Use POST for token requests, secure storage
Impact: Prevents token theft
```

### =

**4. Invalid Redirect URIs**

```yaml
Vulnerability: Open redirect parameter manipulation
Mitigation: Whitelist allowed redirect URIs
Impact: Prevents token theft via malicious redirects
```

### =

**5. Insufficient Scope Validation**

```yaml
Vulnerability: Client receives more permissions than needed
Mitigation: Implement principle of least privilege
Impact: Reduces attack surface
```

## =� Testing & Validation

### >� **Token Testing**

```javascript
// Test token endpoint
async function testTokenEndpoint() {
  try {
    const response = await fetch('https://auth.example.com/token', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({
        grant_type: 'client_credentials',
        client_id: 'test_client',
        client_secret: 'test_secret',
        scope: 'read'
      })
    });

    const data = await response.json();

    if (!response.ok) {
      throw new Error(`Token request failed: ${data.error_description}`);
    }

    return data;
  } catch (error) {
    console.error('Token test failed:', error);
    throw error;
  }
}
```

### =

**OAuth 2.0 Security Test Suite**

```yaml
Test Cases:
  1. Valid authorization flow
  2. Invalid client credentials
  3. Expired token rejection
  4. Invalid scope requests
  5. CSRF protection validation
  6. PKCE challenge verification
  7. Redirect URI validation
  8. Token revocation testing
```

### =� **Security Headers**

```javascript
// Implement security headers
app.use((req, res, next) => {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('X-XSS-Protection', '1; mode=block');
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  res.setHeader('Content-Security-Policy', "default-src 'self'");
  next();
});
```

## = Integration Examples

### = **Social Login Implementation**

```javascript
// Google OAuth 2.0 Integration
const googleConfig = {
  client_id: 'your_google_client_id',
  redirect_uri: 'https://yourapp.com/auth/google/callback',
  scope: 'openid email profile',
  authorization_endpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
  token_endpoint: 'https://oauth2.googleapis.com/token',
  userinfo_endpoint: 'https://www.googleapis.com/oauth2/v2/userinfo'
};

function initiateGoogleAuth() {
  const authUrl = `${googleConfig.authorization_endpoint}?` +
    `client_id=${googleConfig.client_id}&` +
    `redirect_uri=${googleConfig.redirect_uri}&` +
    `response_type=code&` +
    `scope=${googleConfig.scope}&` +
    `state=${generateState()}`;

  window.location.href = authUrl;
}
```

### = **Enterprise SSO (SAML + OAuth)**

```yaml
Integration Pattern:
  1. User authenticates via SAML SSO
  2. Identity provider issues SAML assertion
  3. OAuth bridge converts SAML to OAuth tokens
  4. Application receives OAuth tokens
  5. Access resources with tokens

Providers: Okta, Azure AD, ADFS, OneLogin
```

### =� **Mobile OAuth Implementation**

```swift
// iOS OAuth Implementation
import AppAuth

class OAuthManager {
    private var currentAuthorizationFlow: OIDExternalUserAgentSession?

    func authenticateWithOAuth() {
        let configuration = OIDServiceConfiguration(
            authorizationEndpoint: URL(string: "https://auth.example.com/auth")!,
            tokenEndpoint: URL(string: "https://auth.example.com/token")!
        )

        let request = OIDAuthorizationRequest(
            configuration: configuration,
            clientId: "your_client_id",
            clientSecret: nil,
            scopes: ["openid", "profile", "email"],
            redirectURL: URL(string: "yourapp://oauth/callback")!,
            responseType: OIDResponseTypeCode,
            additionalParameters: nil
        )

        // Perform authentication
        currentAuthorizationFlow = OIDAuthState.authState(
            byPresenting: request,
            presenting: self,
            callback: { authState, error in
                if let authState = authState {
                    // Successfully authenticated
                    self.handleAuthenticationSuccess(authState)
                } else {
                    // Authentication failed
                    self.handleAuthenticationError(error)
                }
            })
    }
}
```

## =� Resources

### =� **Official Documentation**

* [OAuth 2.0 RFC 6749](https://tools.ietf.org/html/rfc6749)
* [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)
* [OAuth 2.1 Draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-08)

### =' **Libraries & SDKs**

* [Node.js: Passport.js](http://www.passportjs.org/)
* [Java: Spring Security OAuth](https://spring.io/projects/spring-security-oauth)
* [Python: Authlib](https://authlib.org/)
* [Ruby: Doorkeeper](https://github.com/doorkeeper-gem/doorkeeper)

### >� **Testing Tools**

* [OAuth 2.0 Playground](https://developers.google.com/oauthplayground)
* [OAuth 2.0 Debugger](https://oauthdebugger.com/)
* [JWT.io](https://jwt.io/)

### =� **Security Guidelines**

* [OWASP OAuth 2.0 Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth_2_0_Cheat_Sheet.html)
* [OAuth 2.0 Security Best Current Practice](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-15)

***

## =� **Implementation Checklist**

### **Security Configuration**

* [ ] Implement PKCE for public clients
* [ ] Use cryptographically random state parameter
* [ ] Validate redirect URIs (whitelist approach)
* [ ] Implement proper token storage
* [ ] Add token expiration handling
* [ ] Secure token endpoint communication

### **Functionality Testing**

* [ ] Test complete authorization flow
* [ ] Verify token validation logic
* [ ] Test error handling scenarios
* [ ] Validate scope enforcement
* [ ] Test token refresh mechanism
* [ ] Verify logout/revocation process

### **Compliance & Standards**

* [ ] Follow OAuth 2.0 security best practices
* [ ] Implement GDPR-compliant user data handling
* [ ] Add audit logging for security events
* [ ] Document security architecture
* [ ] Perform regular security assessments

***

*Catatan Seekor: OAuth - Comprehensive OAuth 2.0 and OpenID Connect implementation guide*
