Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow mounting oidc-provider to a next.js application #1229

Closed
wants to merge 5 commits into from

Conversation

lbennett-stacki
Copy link

@lbennett-stacki lbennett-stacki commented Sep 18, 2023

Allow mounting of the oidc server to a next.js application.

@panva
Copy link
Owner

panva commented Sep 18, 2023

Seeing the doc changes this is then a breaking change, isn't it?

Copy link
Owner

@panva panva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In your original PR you wrote

I noticed the discovery paths were wrong, but also some generated paths like ones used by interactionFinished would be incorrect.

Would you mind simply demonstrating the issue first before continuing with this PR? I'm afraid you're doing breaking changes that I will not accept right now anyway. I'm being upfront about it so that you don't waste your time.

Presenting the issue in a project first would help to maybe add a nextjs run to the test suite as previously asked for here.

lib/helpers/remove_trailing_slash.js Show resolved Hide resolved
@@ -115,7 +116,7 @@ class Provider extends events.EventEmitter {

super();

this.issuer = issuer;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you removing the trailing slash in the issuer identifier?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In tests I was getting some failures because a route had double slashes, which didn't match the actual/expected value which had a single slash.

I thought it would be nice to ensure everything would always have a trailing slash removed. But I'm happy to put this back how it was and maybe update how the paths are generated elsewhere

lib/provider.js Outdated Show resolved Hide resolved
@lbennett-stacki
Copy link
Author

Seeing the doc changes this is then a breaking change, isn't it?

Would you mind simply demonstrating the issue first before continuing with this PR?

Sure! I'll work backwards and demonstrate the issue. Either way I'm sure I could get something that is backwards compat working too.

Is it specifically that it must be mounted under /oidc for specification reason or is it just any breaking change likely wont get shipped?

@panva
Copy link
Owner

panva commented Sep 21, 2023

Well the docs and then the tests demonstrated how to mount under a particular path, which is about the only reason i can imagine i would use a mounting strategy, to mount to an existing app under a unique path.

So my conclusion of seeing existing tests changed is that you're introducing a breaking change, apologies if that's not the case, i just can't by looking at the change set.

@lbennett-stacki lbennett-stacki force-pushed the router-prefix branch 2 times, most recently from 2feb48d to bc29267 Compare September 22, 2023 05:15
@@ -71,8 +71,9 @@ export default async (ctx, accessToken) => {
}

{
const expected = new URL(ctx.oidc.urlFor(ctx.oidc.route)).href;
Copy link
Owner

@panva panva Sep 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to normalize the URL's scheme and hostname case independent, introduced 3 weeks ago in b72d668. You'd need to revert this change in your PR.

@panva
Copy link
Owner

panva commented Sep 22, 2023

  • Allow implementor to provide a mount path for the OIDC server

The provider is already mountable in a stable manner. If this is not working for next.js then please, provide a working minimal sample so that it may be included in the test suite and this issue resolved. The changes you're introducing in this PR are breaking the existing mounting interactions with some frameworks.

@panva panva changed the title Router prefix feat: allow mounting oidc-provider to a next.js application Sep 22, 2023
@AlexCaston
Copy link

I've previously mounted node-oidc-provider on a NextJS application with success, without needing to modify the original oidc code. You only need to use the custom server implementation of NextJS. I made my custom server a Koa server, then serve all the oidc routes and fallback to nextjs.

import { promisify } from 'node:util' // eslint-disable-line
import { parse } from 'node:url' // eslint-disable-line
import Koa from 'koa'
// import koaMount from 'koa-mount'
import next from 'next'
import helmet from 'helmet'
import { oidc } from './oidc/provider'
import { OidcRouter } from './oidc/routes'
import { PORT, IS_DEV, HOSTNAME } from './env'

// nextjs
const app = next({
  dev: IS_DEV,
  hostname: HOSTNAME,
  port: PORT,
})
const nextHandler = app.getRequestHandler()

// koa
const koa = new Koa()

if (process.env.NODE_ENV === 'production') {
  const directives = helmet.contentSecurityPolicy.getDefaultDirectives()
  delete directives['form-action']
  const pHelmet = promisify(helmet({
    contentSecurityPolicy: {
      useDefaults: false,
      directives,
    },
  }))
  koa.use(async (ctx, next) => {
    await pHelmet(ctx.req, ctx.res)
    return next() // eslint-disable-line
  })
}

app.prepare().then(() => {
  koa.use(OidcRouter(oidc).routes())
  koa.use(async (ctx) => {
    const oidcRegex = /^\/(\.well-known|auth|backchannel|device|session|token|jwks|request|reg|token|me)/
    if (oidcRegex.test(ctx.path)) {
      return oidc.callback()(ctx.req, ctx.res)
    } else {
      const parsedUrl = parse(ctx.url, true)
      await nextHandler(ctx.req, ctx.res, parsedUrl)
    }
  })
  koa.listen(PORT)
})

Then you can create your pages/interaction/[uid].tsx file and serve the interaction page there. You can use getServerSideProps there to obtain the interactionDetails:

export const getServerSideProps = (async (ctx) => {
  const { uid, prompt, params, session } = await oidc.interactionDetails(ctx.req, ctx.res)
  const client = await oidc.Client.find(params.client_id as string)

  const props = {
    uid,
    prompt,
    params,
    session,
    client,
  }

  return {
    props: process.env.NODE_ENV === 'production'
      ? props
      : removeUndefined(props),
  }

Your custom routes go in './oidc/routes' and it's just a koa-router

@panva
Copy link
Owner

panva commented Oct 17, 2023

This has become stale, closing for now.

@panva panva closed this Oct 17, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Jan 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants