> For the complete documentation index, see [llms.txt](https://oten.gitbook.io/identity-support/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://oten.gitbook.io/identity-support/integration/prerequisites/pkce-implementation-guide/step-1-choose-oauth-library.md).

# 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 ✅
