Okta Integration (Using OpenID Connect)

Advanced

About OpenID Connect

OpenID Connect is an authentication layer built on top of OAuth 2.0 that allows applications to verify the identity of users and obtain basic profile information. It provides a standardized way for applications to authenticate users through external identity providers without requiring users to create separate accounts for each application.

When Package Manager is configured with OpenID Connect:

  • Users authenticate through your organization’s identity provider (such as Okta, Microsoft Entra ID, or other OIDC-compliant providers)
  • Package Manager receives identity information and group memberships from the provider
  • Access to repositories and Package Manager features is controlled through scope mappings based on user roles and group memberships
  • Users benefit from single sign-on (SSO) across your organization’s applications

OpenID Connect is particularly useful for organizations that want to centralize user management and provide seamless access to Package Manager without requiring separate credentials.

Package Manager can integrate with Okta through the use of the OpenID Connect authentication provider.

Using this integration, user authentication will be provided by Okta. Group membership details may also be provided by Okta for scope mapping.

Configuration example

This is an example of configuring OpenID Connect authentication with Okta. You will need to modify the values to match your Okta application. See the Configuration section below for more details on each individual setting.

For additional information about configuring Okta, refer to the Okta documentation on Authorization servers.

/etc/rstudio-pm/rstudio-pm.gcfg
; Address must be configured when using OpenID Connect authentication.
; Address is a public URL for this Posit Package Manager server in the format
; of http(s)://[HOST:PORT]. If Package Manager is deployed behind an HTTP proxy,
; provide the URL as seen by users through the proxy.
[Server]
Address = "https://packagemanager.example.com"

[OpenIDConnect]
Issuer = https://your-organization.okta.com/oauth2/default
ClientId = 0oa2e0pp4hsQlHugh0h8

; Include a ClientSecret if your Okta application requires it
;ClientSecret = "<secret>"

; Force users to authenticate with Okta every time they sign in to
; Package Manager, rather than relying on existing sessions.
;RequireLogin = true

; Specify how long Package Manager will accept a user's authentication before
; requiring them to reauthenticate with Okta (defaults to 12 hours).
;MaxAuthenticationAge = "24h"

; When troubleshooting an OpenID Connect problem, more verbose logging
; is produced by uncommenting the following line:
;Logging = true

; Basic repository access for all Okta users. Don't include this unless you need
; to grant a default level of access to all authenticated users.
;Scope = "repos:read:*"

; Example group-based scope mapping
; Uncomment and modify based on your Okta groups
;[GroupToScopeMapping "PackageManager-Admins"]
;Scope = "global:admin"

;[GroupToScopeMapping "PackageManager-Developers"]
;Scope = "sources:write:*"

Okta-specific Notes

When using Okta as your OpenID Connect provider:

  • Package Manager automatically includes the groups scope in authentication requests to Okta, providing group membership information for scope mapping. If you don’t want automatic group scope inclusion, or if your Okta configuration does not support a groups scope, you can disable it:

    /etc/rstudio-pm/rstudio-pm.gcfg
    [OpenIDConnect]
    NoAutoGroupsScope = true
  • Group names in Okta are case-sensitive and must match exactly in your GroupToScopeMapping sections.

  • Okta does not support PKCE (Proof Key for Code Exchange) for device authorization flows. When using device authorization with Okta, ensure that EnableDevicePKCE remains set to its default value of false. Do not enable PKCE for device flows when using Okta as your OpenID Connect provider.

Configuring Authenticated Repositories

This section provides step-by-step instructions for creating and configuring authenticated repositories using OpenID Connect.

  1. Create the authenticated repository

    Create a new repository that requires authentication by running rspm create repo with the --authenticated flag:

    Terminal
    # Create an authenticated CRAN repository:
    rspm create repo --name=cran --description='Access CRAN packages' --authenticated
    rspm subscribe --repo=cran --source=cran
    
    # Create an authenticated PyPI repository:
    rspm create repo --name=pypi --type=python --description='Access PyPI packages' --authenticated
    rspm subscribe --repo=pypi --source=pypi
    
    # Create an authenticated Bioconductor repository:
    rspm create repo --type=bioconductor --name=bioconductor --description='Access Bioconductor packages' --authenticated

    Or edit an existing repository to require authentication:

    Terminal
    rspm edit repo --name=cran --authenticated
  2. Configure repository access

    Users need the repos:read scope to access authenticated repositories. You can grant this access in several ways:

    • Grant access to all authenticated users:

      /etc/rstudio-pm/rstudio-pm.gcfg
      [OpenIDConnect]
      Scope = "repos:read:*"
    • Grant access based on group membership:

      /etc/rstudio-pm/rstudio-pm.gcfg
      [GroupToScopeMapping "PackageManager-Users"]
      Scope = "repos:read:cran"
      Scope = "repos:read:pypi"
      Scope = "repos:read:internal-dev"
    • Grant access based on roles:

      /etc/rstudio-pm/rstudio-pm.gcfg
      [OpenIDConnect]
      RoleClaim = "roles"
      
      [RoleToScopeMapping "developer"]
      Scope = "repos:read:*"

    Refer to the OpenID Connect Scope Mapping Guide for detailed examples of scope mapping configurations.

  3. Configure client access

    Instruct users to configure Python to use OpenID Connect for authentication.

    Warning

    As of this release, client support for R package installation from authenticated repositories using OpenID Connect is in development and is expected to be available for Posit Workbench, Posit Connect, and open source R in the near future. Token-based authentication is currently available as an alternative.

Configuration

Defining an OpenID Connect issuer

Package Manager requires metadata for the OpenID Connect identity provider that it is being integrated with. This is specified through the configuration option OpenIDConnect.Issuer. The issuer must be an HTTPS URL and the location of the /.well-known/openid-configuration discovery metadata for OpenID Connect.

Note

The HTTPS certificate associated with the issuer URL must be valid and associated with a valid certificate authority. Self-signed certificates will not be accepted.

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
Issuer = "https://openid.example.com"
Note

In the example above the metadata URL would be https://openid.example.com/.well-known/openid-configuration

Obtaining a client ID and client secret

In order for Package Manager to use OpenID Connect authentication, you will need a client ID. Some OpenID Connect providers also require a client secret.

If you want to support device authorization to allow users to authenticate from command line applications, you will need your OpenID Connect application to support device authorization. If your provider is not able to support device authorization, you can use Package Manager’s internal device authorization flow by setting the Authentication.DeviceAuthType configuration option to internal.

Different vendors require specific steps in order to obtain a client ID and a client secret. You will likely be asked for some information about Package Manager during this process, for example:

  • Application Type: “Native Application”

  • Redirect URL: Use your Package Manager server address with the path /__login__/callback (i.e. https://packagemanager.example.com/__login__/callback).

  • Logout URL: Use your Package Manager server address with the path /__logout__ (i.e. https://packagemanager.example.com/__logout__).

  • Origin URL: Use your Package Manager server URL (i.e. https://packagemanager.example.com).

  • Grant types: Authorization Code, Device Authorization.

Please consult your OpenID Connect authentication provider’s documentation for further information.

Note

We recommend using a distinct set of credentials for each application you configure to use with OpenID Connect.

Add the client ID and secret to your configuration file as shown in the example below.

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
ClientId = "<CLIENT ID>"
ClientSecret = "<CLIENT SECRET>"

With OpenIDConnect.ClientId and either OpenIDConnect.ClientSecret or OpenIDConnect.ClientSecretFile configured, you can use your account to sign in to Package Manager.

Note

The ClientSecret or ClientSecretFile can be encrypted to avoid leakage of the credential. See the Property Types configuration appendix for details.

PKCE (Proof Key for Code Exchange) Configuration

PKCE is a security extension to OAuth 2.0 that helps prevent authorization code interception attacks. Package Manager provides configuration options to control PKCE usage:

Default PKCE Behavior

By default, Package Manager:

  • Enables PKCE for authorization code flows (web-based login)
  • Disables PKCE for device authorization flows (command-line authentication)

Security Recommendations

For optimal security, we recommend using PKCE in all scenarios where it is supported.

Configuration Examples

For maximum security (recommended):

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
ClientId = "<CLIENT ID>"
ClientSecret = "<CLIENT SECRET>"
; PKCE is enabled by default for authorization code flow
; DisablePKCE = false  ; (default)

For public clients without client secrets:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
ClientId = "<CLIENT ID>"
; No ClientSecret specified
; PKCE is enabled by default for authorization code flow

For providers that don’t support PKCE:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
ClientId = "<CLIENT ID>"
ClientSecret = "<CLIENT SECRET>"
DisablePKCE = true

For device flows with PKCE support:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
ClientId = "<CLIENT ID>"
EnableDevicePKCE = true
Warning

Some OpenID Connect providers may not support PKCE for all flow types. Consult your provider’s documentation and test your configuration thoroughly. If you encounter authentication issues, you may need to disable PKCE for specific flows.

Session Management and Reauthentication

Package Manager provides configuration options to control how user sessions are managed and when users must reauthenticate:

Require Login on Each Access

The OpenIDConnect.RequireLogin setting forces users to authenticate with the OpenID Connect provider every time they sign in to Package Manager, rather than relying on existing sessions.

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
RequireLogin = true

When to use RequireLogin:

  • High-security environments where fresh authentication is required for each login
  • Shared or public workstations where sessions should not persist
  • Compliance requirements that mandate reauthentication for each session
  • Testing scenarios where you need to verify authentication flows repeatedly
Note

Enabling RequireLogin may impact user experience as users will need to authenticate every time they sign in to Package Manager, even if they have recently authenticated.

Maximum Authentication Age

The OpenIDConnect.MaxAuthenticationAge setting specifies how long Package Manager will accept a user’s authentication before requiring them to reauthenticate with the OpenID Connect provider.

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
MaxAuthenticationAge = "24h"

Common authentication age configurations:

  • 1h - High security environments, frequent reauthentication
  • 8h - Standard work day, reauthenticate daily
  • 24h - Moderate security, reauthenticate daily
  • 168h (7 days) - Low security environments, weekly reauthentication

When to configure MaxAuthenticationAge:

  • Compliance requirements that specify maximum session durations
  • Environments with varying security requirements based on data sensitivity
  • Organizations that want to balance security with user convenience
  • Scenarios where you want to ensure users reauthenticate periodically without forcing authentication on every access
Important

The MaxAuthenticationAge setting cannot be set to zero unless RequireLogin is enabled. Setting MaxAuthenticationAge to zero forces authentication on every access, which is equivalent to enabling RequireLogin. For clarity and to avoid confusion, use RequireLogin = true instead when you want to force authentication on every access.

Combined Session Management Example

For high-security environments, you might combine these settings:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
ClientId = "<CLIENT ID>"
ClientSecret = "<CLIENT SECRET>"
RequireLogin = false
MaxAuthenticationAge = "4h"

This configuration allows users to maintain sessions for up to 4 hours before requiring reauthentication, providing a balance between security and usability.

Global Authentication Session Settings

In addition to the OpenID Connect-specific session settings above, Package Manager has global authentication settings that control session behavior for all authentication methods:

Authentication Lifetime

The Authentication.Lifetime setting controls the maximum duration for any authenticated session in Package Manager, regardless of activity:

/etc/rstudio-pm/rstudio-pm.gcfg
[Authentication]
Lifetime = "72h"  ; Default: users must reauthenticate every 3 days

This setting acts as an absolute session limit. Even if a user remains active, they will be required to reauthenticate after this period expires.

Authentication Inactivity

The Authentication.Inactivity setting specifies how long a session can remain idle before requiring reauthentication:

/etc/rstudio-pm/rstudio-pm.gcfg
[Authentication]
Inactivity = "24h"  ; Default: idle sessions expire after 24 hours

Important interactions:

  • If Authentication.Inactivity is greater than Authentication.Lifetime, it has no effect
  • Set to zero (0) to disable inactivity-based session expiration
  • Inactivity is reset by user activity in Package Manager

How Session Settings Work Together

The various session settings work together to provide layered session control:

  1. OpenIDConnect.MaxAuthenticationAge: Controls how fresh the authentication with the OpenID Connect provider must be
  2. OpenIDConnect.RequireLogin: Forces fresh authentication with the provider on every access
  3. Authentication.Lifetime: Sets the absolute maximum session duration in Package Manager
  4. Authentication.Inactivity: Expires idle sessions to reduce security exposure

Example configuration for high-security environment:

/etc/rstudio-pm/rstudio-pm.gcfg
[Authentication]
Lifetime = "8h"      ; Maximum 8-hour sessions
Inactivity = "2h"    ; Expire after 2 hours of inactivity

[OpenIDConnect]
MaxAuthenticationAge = "4h"  ; Require fresh OIDC auth every 4 hours
RequireLogin = false         ; Don't force login on every access

This example ensures users reauthenticate with the OpenID Connect provider every 4 hours, sessions expire after 2 hours of inactivity, and no session lasts longer than 8 hours regardless of activity.

Access Control and Scope Mapping

Package Manager uses scope-based access control to determine what actions users can perform. When using OpenID Connect authentication, user access is controlled through scope mappings based on:

  • Base scopes: Default scopes assigned to all users of this provider via OpenIDConnect.Scope
  • Group-based scopes: Additional scopes assigned based on group membership via GroupToScopeMapping sections
  • Role-based scopes: Additional scopes assigned based on user roles via RoleToScopeMapping sections

Available Package Manager Scopes

Package Manager supports the following scopes for token-based access:

Scope Description
global:admin Grants full access to manage the Package Manager server.
sources:write:<sources> Grants read and write access to sources, such as uploading packages, removing packages, creating Git builders, and importing Git credentials. Access can be limited to specific sources. Replace <sources> with a comma-separated list of sources, or use * for all sources.
repos:read:<repos> Grants read access to authenticated repositories. Access can be limited to specific repositories. Replace <repos> with a comma-separated list of repos, or use * for all repos.
blocklist:admin Grants full access to manage the blocklist.
blocklist:read Grants read access to the blocklist.
metadata:admin Grants full access to manage metadata.

Basic Scope Configuration

You can assign default scopes to all users authenticating through the OpenID Connect provider:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
Scope = "repos:read:*"

For more advanced scope mapping examples, see the OpenID Connect Scope Mapping Guide.

Device Authorization

Package Manager supports device authorization flow for scenarios where users need to authenticate from environments without web browsers (e.g., command-line applications, headless servers, or CI/CD environments).

External vs. Internal Device Authorization

Package Manager can handle device authorization in two ways:

External Device Authorization

When using external device authorization, Package Manager delegates the entire device flow to your OpenID Connect provider:

  1. The user runs a command-line tool that needs authentication
  2. Package Manager requests a device code from the OpenID Connect provider’s device authorization endpoint
  3. The user visits the provider’s device authorization URL and enters the device code
  4. The user authenticates directly with the OpenID Connect provider
  5. Package Manager receives the authentication result from the provider

This approach requires that your OpenID Connect provider supports the device authorization flow (RFC 8628).

Internal Device Authorization

When using internal device authorization, Package Manager provides its own device authorization interface while still leveraging your OpenID Connect provider for the actual authentication:

  1. The user runs a command-line tool that needs authentication
  2. Package Manager generates its own device code and displays instructions
  3. The user visits Package Manager’s device authorization page (https://packagemanager.example.com/device)
  4. Package Manager redirects the user to the OpenID Connect provider for authentication
  5. The user enters the device code on Package Manager’s page
  6. After successful authentication with the provider, Package Manager completes the device flow

This approach allows Package Manager to provide device authorization even when your OpenID Connect provider doesn’t support the device flow, or when you prefer to use Package Manager’s interface for a consistent user experience.

Configuration Options

The Authentication.DeviceAuthType setting controls how device authorization is handled:

  • auto (default): Uses the external behavior when OpenID Connect is configured and the provider supports device authorization; uses internal behavior otherwise
  • external: Always uses the OpenID Connect provider’s device authorization endpoint (requires provider support)
  • internal: Always uses Package Manager’s internal device authorization interface
  • off: Disables device authorization flow entirely (not recommended for command-line usage)
/etc/rstudio-pm/rstudio-pm.gcfg
[Authentication]
DeviceAuthType = "internal"

When to Use Internal Device Authorization

Consider using internal device authorization (DeviceAuthType = "internal") when:

  • Your OpenID Connect provider doesn’t support device authorization: Some providers may not implement RFC 8628, and some providers may not be configured to enable it.
  • You want a consistent user experience: Package Manager’s device flow integrates seamlessly with its web interface

When to Use External Device Authorization

Consider using external device authorization (DeviceAuthType = "external") when:

  • Your provider supports it: If your OpenID Connect provider has a robust device authorization implementation
  • You want provider-native experience: Users interact directly with your organization’s identity provider
  • You have provider-specific requirements: Some organizations require all authentication to flow through the provider’s interface

Regardless of the DeviceAuthType setting, the actual user authentication always occurs through your configured OpenID Connect provider. The setting only controls whether Package Manager or the external provider handles the device flow coordination.

Important

If you set DeviceAuthType = "external" but your OpenID Connect provider doesn’t support device authorization, command-line authentication will fail. Test your configuration thoroughly and use DeviceAuthType = "internal" if necessary.

Customizing OpenID Connect

The Package Manager default configuration relies on standard OpenID Connect values for authentication. However, some vendors may use proprietary values. This is especially true for OpenID scopes and claims. Package Manager offers some options that allow adjusting these values to match your OpenID Connect authentication service provider.

Customizing scopes

Package Manager support for OpenID Connect relies on the standard OpenID Connect scopes openid, email and profile.

You can include additional scopes if necessary by using the configuration option OpenIDConnect.CustomScope. You should define one additional scope per line. For example:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
CustomScope = "my_custom_scope1"
CustomScope = "my_custom_scope2"
Note

Custom scopes are generally expected by the authentication provider in order to return non-standard claims.

Customizing claims

By default, the returning JWT (JSON Web Token) IDToken payload is expected to return the following claims:

  • sub - This will be user unique identifier (UniqueID) in Package Manager. Configurable via the option OpenIDConnect.UniqueIdClaim.

  • preferred_username - This will be the user’s username in Package Manager. This value becomes the sub claim in Package Manager tokens and is logged when the user authenticates with the token. Configurable via the option OpenIDConnect.UsernameClaim.

  • groups (optional, but default for Okta) - This will be the group memberships used for scope mapping in Package Manager. Configurable via the options OpenIDConnect.GroupsClaim and OpenIDConnect.NoAutoGroupsScope. Package Manager will not apply group-based scope mappings if not present or blank.

Note

Package Manager does not store (apart from logging) user profile information like username, first name, last name, or email address from OpenID Connect tokens. Information from the ID token is only used for authentication and authorization. Username and email information may be recorded in some logs.

Additional OpenID Connect options

In the event that a claim cannot present groups as a list of distinct values, you may use the OpenIDConnect.GroupsSeparator setting to specify a separator string that will be used to split a single value into a list. For example, if the groups attribute contains a value of the form, group_1|group_2, set:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
GroupsSeparator = "|"

Similarly, for role claims, you can use OpenIDConnect.RolesSeparator:

/etc/rstudio-pm/rstudio-pm.gcfg
[OpenIDConnect]
RolesSeparator = "|"
Tip

For detailed examples of scope mapping configurations, see the OpenID Connect Scope Mapping Guide.

Back to top