# Step 1: Choose OAuth Library

The first step in integrating Oten IDP is selecting the right OAuth 2.0 / OpenID Connect library for your technology stack. **IMPORTANT: Your chosen library must support JAR (JWT-Secured Authorization Request) as Oten IDP requires it for all authorization requests.**

**Can't implement JAR?** If your application cannot support JAR due to technical constraints, contact <support@oten.dev> to discuss enabling traditional OAuth flow as a temporary solution.

> 📖 **Need the big picture?** Check out the [Integration Flow Overview](broken://pages/iMMrTD1lQOMbxxvheKAz) to understand how this step fits into the complete process.

## 🎯 What You'll Learn

In this step, you will:

* Understand JAR (JWT-Secured Authorization Request) requirements
* Choose libraries that support JAR and JWT signing
* Install and configure your chosen library with JAR support
* Understand the trade-offs between different options

## 🚨 JAR Requirement - CRITICAL

**Oten IDP requires JAR (JWT-Secured Authorization Request) for ALL authorization requests.** Your chosen library must support:

### Required JAR Features

* ✅ **JWT Creation and Signing** (RS256, HS256, or EdDSA)
* ✅ **Custom JWT Claims** (ability to add OAuth parameters to JWT payload)
* ✅ **Key Management** (RSA keys for RS256 or client secret for HS256)
* ✅ **Request Parameter Support** (sending JWT in `request` parameter)

### ❌ Libraries That Won't Work

Libraries that only support traditional OAuth query parameters will **NOT** work with Oten IDP:

```javascript
// ❌ This approach will be REJECTED by Oten IDP
const authURL = `https://account.oten.com/v1/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectURI}&response_type=code&scope=openid profile email&state=${state}`;
```

### ✅ What You Need

Libraries that can create signed JWTs and send them in the `request` parameter:

```javascript
// ✅ This is the ONLY way that works with Oten IDP
const requestJWT = await createJAR(authParams, privateKey);
const authURL = `https://account.oten.com/v1/oauth/authorize?client_id=${clientId}&request=${requestJWT}`;
```

## 📚 Library Categories

### Official vs Third-Party Libraries

#### Official Libraries

* **Maintained by platform vendors** (Google, Microsoft, etc.)
* **Well-documented and supported**
* **Regular security updates**
* **Best practices built-in**
* **May need custom JAR implementation**

#### Third-Party Libraries

* **Community-maintained**
* **Often more flexible**
* **May have additional features**
* **Varying quality and support levels**
* **Check JAR support before choosing**

#### Oten Official Libraries

* **Specifically designed for Oten IDP**
* **Built-in JAR support**
* **Optimized for Oten features**
* **Direct support from Oten team**

### Client Type Considerations

#### Confidential Clients (Server-Side)

* **Can securely store client secrets**
* **Token exchange happens on server**
* **More security options available**
* **Examples**: Web servers, APIs, backend services

#### Public Clients (Client-Side)

* **Cannot store secrets securely**
* **Must use PKCE for security**
* **Tokens handled in browser/device**
* **Examples**: SPAs, mobile apps, desktop apps

## 🛠️ Technology-Specific Recommendations

### JavaScript/Node.js

#### For Server-Side (Node.js)

```bash
# Recommended: openid-client
npm install openid-client

# Alternative: passport with OAuth strategy
npm install passport passport-oauth2
```

**openid-client** - Most comprehensive

```javascript
const { Issuer } = require('openid-client');

// Discover Oten configuration
const otenIssuer = await Issuer.discover('https://account.oten.com');

const client = new otenIssuer.Client({
  client_id: 'your-client-id',
  client_secret: 'your-client-secret',
  redirect_uris: ['https://yourapp.com/callback'],
  response_types: ['code'],
});
```

#### For Client-Side (Browser/SPA)

```bash
# Recommended: oidc-client-ts
npm install oidc-client-ts

# Alternative: auth0-spa-js (more opinionated)
npm install @auth0/auth0-spa-js
```

**oidc-client-ts** - Standards compliant

```javascript
import { UserManager } from 'oidc-client-ts';

const userManager = new UserManager({
  authority: 'https://account.oten.com',
  client_id: 'your-client-id',
  redirect_uri: 'https://yourapp.com/callback',
  response_type: 'code',
  scope: 'openid profile email',
  post_logout_redirect_uri: 'https://yourapp.com',
});
```

### Python

#### Recommended Libraries

```bash
# Most comprehensive: authlib
pip install authlib

# Alternative: requests-oauthlib
pip install requests-oauthlib

# For Django: django-oauth-toolkit
pip install django-oauth-toolkit

# For Flask: flask-oauthlib
pip install flask-oauthlib
```

**Authlib** - Modern and comprehensive

```python
from authlib.integrations.flask_client import OAuth

oauth = OAuth(app)
oten = oauth.register(
    name='oten',
    client_id='your-client-id',
    client_secret='your-client-secret',
    server_metadata_url='https://account.oten.com/.well-known/openid_configuration',
    client_kwargs={
        'scope': 'openid profile email'
    }
)
```

### Java

#### Spring Boot (Recommended)

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
```

**Spring Security OAuth2**

```yaml
# application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          oten:
            client-id: your-client-id
            client-secret: your-client-secret
            scope: openid,profile,email
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
        provider:
          oten:
            authorization-uri: https://account.oten.com/v1/oauth/authorize
            token-uri: https://account.oten.com/v1/oauth/token
            user-info-uri: https://account.oten.com/v1/oauth/userinfo
            jwk-set-uri: https://account.oten.com/.well-known/jwks.json
```

#### Alternative: pac4j

```xml
<dependency>
    <groupId>org.pac4j</groupId>
    <artifactId>pac4j-oidc</artifactId>
    <version>5.7.0</version>
</dependency>
```

### C#/.NET

#### ASP.NET Core (Recommended)

```bash
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect
```

**OpenID Connect Authentication**

```csharp
services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    options.Authority = "https://account.oten.com";
    options.ClientId = "your-client-id";
    options.ClientSecret = "your-client-secret";
    options.ResponseType = "code";
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("email");
    options.CallbackPath = "/signin-oidc";
});
```

### PHP

#### Recommended Libraries

```bash
# Most popular: league/oauth2-client
composer require league/oauth2-client

# Alternative: thephpleague/oauth2-client
composer require thephpleague/oauth2-client

# For Laravel: laravel/socialite
composer require laravel/socialite
```

**League OAuth2 Client**

```php
use League\OAuth2\Client\Provider\GenericProvider;

$provider = new GenericProvider([
    'clientId'                => 'your-client-id',
    'clientSecret'            => 'your-client-secret',
    'redirectUri'             => 'https://yourapp.com/callback',
    'urlAuthorize'            => 'https://account.oten.com/v1/oauth/authorize',
    'urlAccessToken'          => 'https://account.oten.com/v1/oauth/token',
    'urlResourceOwnerDetails' => 'https://account.oten.com/v1/oauth/userinfo',
]);
```

### Go

#### Oten Official Library (Recommended)

```bash
# Oten go-oauth library with built-in JAR support
go get gitlab.oten.com/go-sdk/go-oauth/client
```

**Oten go-oauth** - Official library with JAR support

```go
import (
    "gitlab.oten.com/go-sdk/go-oauth/client"
    "gitlab.oten.com/go-sdk/go-oauth/jar"
)

// Initialize OAuth client with JAR support
config := &client.Config{
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret", // Optional for public clients
    Endpoint:     client.OtenEndpoint("https://account.oten.com"),
    RedirectURL:  "https://yourapp.com/callback",
    Scopes:       []string{"openid", "profile", "email"},

    // JAR configuration (REQUIRED for Oten IDP)
    JARConfig: &jar.Config{
        SigningMethod: jar.RS256,           // or jar.HS256
        PrivateKey:    loadPrivateKey(),    // RSA private key for RS256
        KeyID:         "your-key-id",       // Key ID from your JWKS
        Issuer:        "your-client-id",    // Usually your client ID
        Audience:      "https://account.oten.com",
    },
}

// Create OAuth client
oauthClient := client.New(config)

// Generate authorization URL with JAR
authURL, err := oauthClient.AuthCodeURL("state-value", client.AccessTypeOffline)
if err != nil {
    log.Fatal(err)
}

// The library automatically creates JAR and sends it in request parameter
fmt.Println("Authorization URL:", authURL)
```

#### Key Features of Oten go-oauth:

* ✅ **Built-in JAR Support**: Automatically creates and signs JWT authorization requests
* ✅ **Multiple Signing Methods**: Supports RS256 (RSA) and HS256 (HMAC) algorithms
* ✅ **PKCE Integration**: Automatic PKCE generation for public clients
* ✅ **Token Management**: Built-in token refresh and validation
* ✅ **JWKS Support**: Automatic public key publishing
* ✅ **Oten Optimized**: Designed specifically for Oten IDP features

#### Alternative: Standard Library (Requires Custom JAR Implementation)

```bash
# Standard OAuth2 library (you'll need to implement JAR manually)
go get golang.org/x/oauth2
go get github.com/golang-jwt/jwt/v5  # For JWT creation
```

**Manual JAR Implementation with Standard Library**

```go
import (
    "golang.org/x/oauth2"
    "github.com/golang-jwt/jwt/v5"
)

// You'll need to implement JAR creation manually
func createJAR(authParams map[string]interface{}, privateKey interface{}) (string, error) {
    now := time.Now()

    claims := jwt.MapClaims{
        // Standard JWT claims
        "iss": authParams["client_id"],
        "aud": "https://account.oten.com",
        "iat": now.Unix(),
        "exp": now.Add(5 * time.Minute).Unix(),
        "jti": generateUUID(),

        // OAuth parameters
        "client_id":              authParams["client_id"],
        "redirect_uri":           authParams["redirect_uri"],
        "response_type":          authParams["response_type"],
        "scope":                  authParams["scope"],
        "state":                  authParams["state"],
        "code_challenge":         authParams["code_challenge"],
        "code_challenge_method":  authParams["code_challenge_method"],
    }

    token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
    token.Header["kid"] = "your-key-id"

    return token.SignedString(privateKey)
}

// Standard OAuth2 config (without JAR support)
config := &oauth2.Config{
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret",
    Endpoint: oauth2.Endpoint{
        AuthURL:  "https://account.oten.com/v1/oauth/authorize",
        TokenURL: "https://account.oten.com/v1/oauth/token",
    },
    RedirectURL: "https://yourapp.com/callback",
    Scopes:      []string{"openid", "profile", "email"},
}

// You'll need to manually create JAR and modify the auth URL
authParams := map[string]interface{}{
    "client_id":              config.ClientID,
    "redirect_uri":           config.RedirectURL,
    "response_type":          "code",
    "scope":                  strings.Join(config.Scopes, " "),
    "state":                  "your-state",
    "code_challenge":         "your-code-challenge",
    "code_challenge_method":  "S256",
}

requestJWT, err := createJAR(authParams, privateKey)
if err != nil {
    log.Fatal(err)
}

// Create authorization URL with JAR
authURL := fmt.Sprintf("%s?client_id=%s&request=%s",
    config.Endpoint.AuthURL,
    config.ClientID,
    requestJWT)
```

**Recommendation**: Use the **Oten go-oauth library** as it handles all JAR complexity automatically and is specifically designed for Oten IDP.

#### Oten go-oauth Library Details

The Oten go-oauth library provides comprehensive OAuth 2.0 and OpenID Connect support with built-in JAR functionality:

**Installation:**

```bash
go get gitlab.oten.com/go-sdk/go-oauth/client
```

**Key Components:**

* `client` package: Main OAuth client with JAR support
* `jar` package: JWT-Secured Authorization Request implementation
* `token` package: Token management and validation
* `jwks` package: JSON Web Key Set handling

**Complete Example:**

```go
package main

import (
    "context"
    "fmt"
    "log"

    "gitlab.oten.com/go-sdk/go-oauth/client"
    "gitlab.oten.com/go-sdk/go-oauth/jar"
)

func main() {
    // Load your RSA private key
    privateKey, err := loadRSAPrivateKey("jar-private-key.pem")
    if err != nil {
        log.Fatal(err)
    }

    // Configure OAuth client with JAR
    config := &client.Config{
        ClientID:    "your-client-id",
        RedirectURL: "https://yourapp.com/callback",
        Scopes:      []string{"openid", "profile", "email"},
        Endpoint:    client.OtenEndpoint("https://account.oten.com"),

        // JAR configuration (automatically handled)
        JARConfig: &jar.Config{
            SigningMethod: jar.RS256,
            PrivateKey:    privateKey,
            KeyID:         "your-key-id",
            Issuer:        "your-client-id",
            Audience:      "https://account.oten.com",
        },
    }

    // Create OAuth client
    oauthClient := client.New(config)

    // Generate authorization URL (JAR is automatically created)
    authURL, err := oauthClient.AuthCodeURL("random-state", client.AccessTypeOffline)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Visit this URL:", authURL)

    // Handle callback (after user authentication)
    // code := "authorization-code-from-callback"
    // token, err := oauthClient.Exchange(context.Background(), code)
    // if err != nil {
    //     log.Fatal(err)
    // }

    // fmt.Printf("Access Token: %s\n", token.AccessToken)
}
```

**Advanced Features:**

```go
// Custom JAR claims
jarConfig := &jar.Config{
    SigningMethod: jar.RS256,
    PrivateKey:    privateKey,
    KeyID:         "your-key-id",
    Issuer:        "your-client-id",
    Audience:      "https://account.oten.com",

    // Custom claims
    CustomClaims: map[string]interface{}{
        "ui_locales":     "en-US",
        "prompt":         "consent",
        "workspace_hint": "workspace-123",
    },
}

// PKCE support for public clients
config := &client.Config{
    ClientID:    "your-public-client-id",
    RedirectURL: "https://yourapp.com/callback",
    Scopes:      []string{"openid", "profile", "email"},
    Endpoint:    client.OtenEndpoint("https://account.oten.com"),

    // Enable PKCE for public clients
    UsePKCE: true,

    JARConfig: jarConfig,
}
```

### Ruby

#### Recommended Libraries

```bash
# Most comprehensive: omniauth
gem install omniauth omniauth-oauth2

# Alternative: oauth2 gem
gem install oauth2

# For Rails: omniauth-rails_csrf_protection
gem install omniauth-rails_csrf_protection
```

**OmniAuth**

```ruby
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :oauth2, 'your-client-id', 'your-client-secret',
    client_options: {
      site: 'https://account.oten.com',
      authorize_url: '/v1/oauth/authorize',
      token_url: '/v1/oauth/token'
    }
end
```

## 🔍 Library Selection Criteria

### JAR Support (CRITICAL for Oten IDP)

**MUST HAVE** features for Oten IDP integration:

* ✅ **JWT Creation and Signing** (RS256, HS256, or EdDSA algorithms)
* ✅ **Custom JWT Claims** (ability to embed OAuth parameters in JWT payload)
* ✅ **Request Parameter Support** (sending JWT in `request` parameter)
* ✅ **Key Management** (RSA private keys or client secrets)
* ✅ **JWKS Integration** (for public key distribution)

### Security Features

Look for libraries that support:

* **JAR (JWT-Secured Authorization Request)** - REQUIRED for Oten
* **PKCE** (essential for public clients)
* **State parameter validation** (CSRF protection)
* **Nonce support** (replay attack prevention)
* **JWT validation** (signature verification)
* **Token refresh** (automatic renewal)

### Standards Compliance

Ensure the library supports:

* **JAR RFC 9101** - CRITICAL for Oten IDP
* **OAuth 2.0 RFC 6749**
* **OpenID Connect Core 1.0**
* **PKCE RFC 7636** (for public clients)
* **JWT RFC 7519**
* **JWKS RFC 7517** (for key distribution)

### Oten Specific Features

Preferred libraries should support:

* **Oten endpoints** (pre-configured)
* **Multi-tenant workspace selection**
* **Oten specific scopes**
* **Built-in error handling** for Oten responses

### Maintenance and Support

Consider:

* **Active development** (recent commits)
* **Security updates** (vulnerability patches)
* **Documentation quality**
* **Community support**
* **Issue response time**
* **Oten compatibility** (if available)

## 📦 Installation Examples

### Package Managers

#### npm (Node.js)

```bash
# Install with npm
npm install openid-client

# Install with yarn
yarn add openid-client

# Install with pnpm
pnpm add openid-client
```

#### pip (Python)

```bash
# Install with pip
pip install authlib

# Install with pipenv
pipenv install authlib

# Install with poetry
poetry add authlib
```

#### Maven (Java)

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
    <version>2.7.0</version>
</dependency>
```

#### NuGet (.NET)

```bash
# Package Manager Console
Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect

# .NET CLI
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect
```

## ⚙️ Configuration Basics

### Environment Variables

Set up your configuration securely:

```bash
# .env file (never commit to version control)
OTEN_CLIENT_ID=your_client_id_here
OTEN_CLIENT_SECRET=your_client_secret_here
OTEN_REDIRECT_URI=https://yourapp.com/callback

# JAR Configuration (REQUIRED for Oten IDP)
JAR_PRIVATE_KEY_PATH=./jar-private-key.pem
JAR_KEY_ID=your-key-id
JWKS_URI=https://yourapp.com/.well-known/jwks.json
```

### Basic Configuration Structure with JAR

Most libraries need to be configured for JAR support:

```javascript
const config = {
  // Client credentials
  clientId: process.env.OTEN_CLIENT_ID,
  clientSecret: process.env.OTEN_CLIENT_SECRET, // Optional for public clients

  // Endpoints
  authorizationURL: 'https://account.oten.com/v1/oauth/authorize',
  tokenURL: 'https://account.oten.com/v1/oauth/token',

  // Application settings
  redirectURI: process.env.OTEN_REDIRECT_URI,
  scope: ['openid', 'profile', 'email'],

  // Security settings
  responseType: 'code',
  grantType: 'authorization_code',

  // JAR Configuration (REQUIRED for Oten IDP)
  jar: {
    enabled: true,                                    // JAR is mandatory
    signingMethod: 'RS256',                          // or 'HS256'
    privateKeyPath: process.env.JAR_PRIVATE_KEY_PATH,
    keyId: process.env.JAR_KEY_ID,
    issuer: process.env.OTEN_CLIENT_ID,      // Usually your client ID
    audience: 'https://account.oten.com'
  }
};
```

### JAR-Specific Configuration

Since Oten IDP requires JAR, you'll need additional setup:

```javascript
// Example for libraries that support JAR
const jarConfig = {
  // JWT signing configuration
  algorithm: 'RS256',                    // Recommended: RS256 with RSA keys
  privateKey: fs.readFileSync(process.env.JAR_PRIVATE_KEY_PATH),
  keyId: process.env.JAR_KEY_ID,

  // JWT claims
  issuer: process.env.OTEN_CLIENT_ID,
  audience: 'https://account.oten.com',
  expirationTime: 300,                   // 5 minutes (recommended)

  // JWKS endpoint for public key distribution
  jwksUri: process.env.JWKS_URI
};
```

## 🔧 Testing Your Library Choice

### Quick Test Setup for JAR Support

1. **Install the library**
2. **Set up JAR configuration** (private key, JWKS endpoint)
3. **Create a simple JAR authorization request**
4. **Test the JWT creation and signing**
5. **Verify the authorization URL format**
6. **Test the complete OAuth flow**

### JAR Testing Checklist

* [ ] **JAR Support**: Library can create and sign JWTs
* [ ] **RS256 Algorithm**: Supports RSA-based JWT signing
* [ ] **Custom Claims**: Can embed OAuth parameters in JWT payload
* [ ] **Key Management**: Handles RSA private keys securely
* [ ] **Request Parameter**: Can send JWT in `request` parameter
* [ ] **JWKS Integration**: Can publish public keys via JWKS endpoint

### General Validation Checklist

* [ ] Library installs without conflicts
* [ ] Documentation is clear and complete
* [ ] JAR examples work with minimal modification
* [ ] PKCE support (if needed for public clients)
* [ ] Token validation features
* [ ] Active community/support
* [ ] Oten IDP compatibility

### Test JAR Implementation

```javascript
// Quick test to verify JAR capability
async function testJARSupport() {
  try {
    // Test JWT creation
    const authParams = {
      client_id: 'test-client',
      redirect_uri: 'https://test.com/callback',
      response_type: 'code',
      scope: 'openid profile email',
      state: 'test-state'
    };

    const requestJWT = await createJAR(authParams);
    console.log('✅ JAR creation successful');

    // Test authorization URL format
    const authURL = `https://account.oten.com/v1/oauth/authorize?client_id=test-client&request=${requestJWT}`;
    console.log('✅ Authorization URL format correct');

    return true;
  } catch (error) {
    console.error('❌ JAR test failed:', error);
    return false;
  }
}
```

***

## 🧭 Navigation

* **← Previous**: [JAR Requirement](broken://pages/o5zOSdwIY61fIuUxsDcR) - Understanding JAR requirements
* **↑ Overview**: [Integration Flow Overview](broken://pages/iMMrTD1lQOMbxxvheKAz) - See the big picture
* **→ Next**: [Step 2: Configure OAuth Client](broken://pages/dEuJONk1kgkDKzShQ91z) - Set up your OAuth client

**Progress**: Step 1 of 5 complete ✅


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://oten.gitbook.io/identity-support/integration/prerequisites/pkce-implementation-guide/step-1-choose-oauth-library.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
