Add blueprint support for auto-login-idp configuration #616

Closed
opened 2026-04-05 17:27:26 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @Copilot on 11/19/2025

Community Contribution License Agreement

By creating this pull request, I grant the project maintainers an unlimited,
perpetual license to use, modify, and redistribute these contributions under any terms they
choose, including both the AGPLv3 and the Fossorial Commercial license terms. I
represent that I have the right to grant this license for all contributed content.

Description

Blueprints can now configure the "Auto Login with External IDP" feature via the auto-login-idp field in the auth section.

Changes

  • Schema: Added auto-login-idp optional integer field to AuthSchema in blueprint types
  • Processing: Sets skipToIdpId directly from the blueprint field in proxyResources.ts
    • Uses IDP ID directly without lookup to avoid issues with duplicate IDP names
    • Sets skipToIdpId on resource creation/update when field is present
  • Example: Updated blueprint.yaml with usage example

Usage

proxy-resources:
  my-app:
    name: My Application
    protocol: http
    full-domain: app.example.com
    auth:
      sso-enabled: true
      auto-login-idp: 1  # IDP ID (integer), shown in frontend
      sso-roles:
        - Member
    targets: [...]

IDPs are referenced by ID (integer) to avoid duplicate name issues. The IDP ID is displayed in the frontend for users to reference.

How to test?

  1. Create a blueprint YAML with the auto-login-idp field set to an IDP ID (integer)
  2. Apply the blueprint via the API
  3. Verify that the resource's skipToIdpId field is set correctly in the database
  4. Access the resource and confirm automatic redirect to the specified IDP occurs
Original prompt

This section details on the original issue you should resolve

<issue_title>Configure 'Auto Login with External IDP' via blueprints</issue_title>
<issue_description>

Discussed in https://github.com/orgs/fosrl/discussions/1761

Originally posted by dephekt October 27, 2025

Summary

I'd like to be able to enable the Auto Login with External IDP setting either via:

  • an org level setting making it default behavior
  • setting a relevant auth config label blueprint on the container

Motivation

I don't want to set the "Auto Login with External IDP" setting on every resource in the UI when I already use blueprints to convey similar config state to Pangolin. And I don't want to write and manage a separate script just to ensure new resources are configured with the setting.

Proposed Solution

I reviewed the NextJS frontend to understand how it determines the state of the UI element in the resource auth configuration dashboard. I see here it posts to the resource to essentially patch it with skipToIdpId: selectedIdpId. This exposes it in the resource schema like this:

$ xh https://api.pangolin.net/v1/resource/123456789 -A bearer -a $PANGOLIN_API | jq '.data'
{
  "resourceId": 123456789,
  "resourceGuid": "foobar",
  "orgId": "org_foobarbaz",
  "niceId": "foobar",
  "name": "FooBar",
  ...
  "setHostHeader": null,
  "enableProxy": true,
  "skipToIdpId": 123456,
  "headers": null
}

Clearly the resource model already supports it and there's an endpoint to set and update the key. So it seems this setting just needs exposed and wired up in the relevant blueprint model. I found that here in server/lib/blueprints/types.ts:

export const AuthSchema = z.object({
    // pincode has to have 6 digits
    pincode: z.number().min(100000).max(999999).optional(),
    password: z.string().min(1).optional(),
    "basic-auth": z.object({
        user: z.string().min(1),
        password: z.string().min(1)
    }).optional(),
    "sso-enabled": z.boolean().optional().default(false),
+   "sso-redirect-idp": z.number().int().positive().optional().nullable(),
    "sso-roles": z
        .array(z.string())
        .optional()
        .default([])
        .refine((roles) => !roles.includes("Admin"), {
            message: "Admin role cannot be included in sso-roles"
        }),
    "sso-users": z.array(z.string().email()).optional().default([]),
    "whitelist-users": z.array(z.string().email()).optional().default([]),
});

Then I think it needs wired to the resource creation in server/lib/blueprints/proxyResources.ts here and similarly during the resource update here.

            const [newResource] = await trx
                .insert(resources)
                .values({
                    orgId,
                    niceId: resourceNiceId,
                    name: resourceData.name || "Unnamed Resource",
                    protocol: protocol || "tcp",
                    http: http,
                    proxyPort: http ? null : resourceData["proxy-port"],
                    fullDomain: http ? resourceData["full-domain"] : null,
                    subdomain: domain ? domain.subdomain : null,
                    domainId: domain ? domain.domainId : null,
                    enabled: resourceEnabled,
                    sso: resourceData.auth?.["sso-enabled"] || false,
+                   skipToIdpId: resourceData.auth?.["sso-redirect-idp"] || null,
                    setHostHeader: resourceData["host-header"] || null,
                    tlsServerName: resourceData["tls-server-name"] || null,
                    ssl: resourceSsl,
                    headers: headers || null,
                    applyRules:
                        resourceData.rules && resourceData.rules.length > 0
                })

Alternatives Considered

I could easily script setting the configuration via the API. It's just another thing to manage and remember, when I prefer to consolidate the resource config within the Docker labels. Keeping it in sync becomes another thing to deal with also.

It's worth considering if it should be an org or other higher level setting, or such a higher setting that can override at the resource level.

Additional Context

No response

</issue_description>

Comments on th...


Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

*Originally created by @Copilot on 11/19/2025* ## Community Contribution License Agreement By creating this pull request, I grant the project maintainers an unlimited, perpetual license to use, modify, and redistribute these contributions under any terms they choose, including both the AGPLv3 and the Fossorial Commercial license terms. I represent that I have the right to grant this license for all contributed content. ## Description Blueprints can now configure the "Auto Login with External IDP" feature via the `auto-login-idp` field in the auth section. ### Changes - **Schema**: Added `auto-login-idp` optional integer field to `AuthSchema` in blueprint types - **Processing**: Sets `skipToIdpId` directly from the blueprint field in `proxyResources.ts` - Uses IDP ID directly without lookup to avoid issues with duplicate IDP names - Sets `skipToIdpId` on resource creation/update when field is present - **Example**: Updated `blueprint.yaml` with usage example ### Usage ```yaml proxy-resources: my-app: name: My Application protocol: http full-domain: app.example.com auth: sso-enabled: true auto-login-idp: 1 # IDP ID (integer), shown in frontend sso-roles: - Member targets: [...] ``` IDPs are referenced by ID (integer) to avoid duplicate name issues. The IDP ID is displayed in the frontend for users to reference. - Fixes fosrl/pangolin#1895 ## How to test? 1. Create a blueprint YAML with the `auto-login-idp` field set to an IDP ID (integer) 2. Apply the blueprint via the API 3. Verify that the resource's `skipToIdpId` field is set correctly in the database 4. Access the resource and confirm automatic redirect to the specified IDP occurs <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> ---- *This section details on the original issue you should resolve* <issue_title>Configure 'Auto Login with External IDP' via blueprints</issue_title> <issue_description> ### Discussed in https://github.com/orgs/fosrl/discussions/1761 <div type='discussions-op-text'> <sup>Originally posted by **dephekt** October 27, 2025</sup> ### Summary I'd like to be able to enable the Auto Login with External IDP setting either via: - an org level setting making it default behavior - setting a relevant auth config label blueprint on the container ### Motivation I don't want to set the "Auto Login with External IDP" setting on every resource in the UI when I already use blueprints to convey similar config state to Pangolin. And I don't want to write and manage a separate script just to ensure new resources are configured with the setting. ### Proposed Solution I reviewed the NextJS frontend to understand how it determines the state of the UI element in the resource auth configuration dashboard. I see [here](https://github.com/fosrl/pangolin/blob/cabf3e96952cfcdc40452f1a4e39800129025801/src/app/%5BorgId%5D/settings/resources/%5BniceId%5D/authentication/page.tsx#L340-L344) it posts to the resource to essentially patch it with `skipToIdpId: selectedIdpId`. This exposes it in the resource schema like this: ```json $ xh https://api.pangolin.net/v1/resource/123456789 -A bearer -a $PANGOLIN_API | jq '.data' { "resourceId": 123456789, "resourceGuid": "foobar", "orgId": "org_foobarbaz", "niceId": "foobar", "name": "FooBar", ... "setHostHeader": null, "enableProxy": true, "skipToIdpId": 123456, "headers": null } ``` Clearly the resource model already supports it and there's an endpoint to set and update the key. So it seems this setting just needs exposed and wired up in the relevant blueprint model. I found that [here](https://github.com/fosrl/pangolin/blob/cabf3e96952cfcdc40452f1a4e39800129025801/server/lib/blueprints/types.ts#L41-L59) in server/lib/blueprints/types.ts: ```diff export const AuthSchema = z.object({ // pincode has to have 6 digits pincode: z.number().min(100000).max(999999).optional(), password: z.string().min(1).optional(), "basic-auth": z.object({ user: z.string().min(1), password: z.string().min(1) }).optional(), "sso-enabled": z.boolean().optional().default(false), + "sso-redirect-idp": z.number().int().positive().optional().nullable(), "sso-roles": z .array(z.string()) .optional() .default([]) .refine((roles) => !roles.includes("Admin"), { message: "Admin role cannot be included in sso-roles" }), "sso-users": z.array(z.string().email()).optional().default([]), "whitelist-users": z.array(z.string().email()).optional().default([]), }); ``` Then I think it needs wired to the resource creation in server/lib/blueprints/proxyResources.ts [here](https://github.com/fosrl/pangolin/blob/cabf3e96952cfcdc40452f1a4e39800129025801/server/lib/blueprints/proxyResources.ts#L581-L602) and similarly during the resource update [here](https://github.com/fosrl/pangolin/blob/cabf3e96952cfcdc40452f1a4e39800129025801/server/lib/blueprints/proxyResources.ts#L213). ```diff const [newResource] = await trx .insert(resources) .values({ orgId, niceId: resourceNiceId, name: resourceData.name || "Unnamed Resource", protocol: protocol || "tcp", http: http, proxyPort: http ? null : resourceData["proxy-port"], fullDomain: http ? resourceData["full-domain"] : null, subdomain: domain ? domain.subdomain : null, domainId: domain ? domain.domainId : null, enabled: resourceEnabled, sso: resourceData.auth?.["sso-enabled"] || false, + skipToIdpId: resourceData.auth?.["sso-redirect-idp"] || null, setHostHeader: resourceData["host-header"] || null, tlsServerName: resourceData["tls-server-name"] || null, ssl: resourceSsl, headers: headers || null, applyRules: resourceData.rules && resourceData.rules.length > 0 }) ``` ### Alternatives Considered I could easily script setting the configuration via the API. It's just another thing to manage and remember, when I prefer to consolidate the resource config within the Docker labels. Keeping it in sync becomes another thing to deal with also. It's worth considering if it should be an org or other higher level setting, or such a higher setting that can override at the resource level. ### Additional Context _No response_</div></issue_description> ## Comments on th... </details> - Fixes fosrl/pangolin#1895 <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/fosrl/pangolin/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/pangolin#616