Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Replacing Payload Auth with a Custom Company Authentication

default discord avatar
jomelorskieelast year
14

Hey so I’ve been banging my head around how to implement the above, I’ve already tried various things like combining disableDefaultStrategy=true then having a custom strategy (that ultimately extracts user information from the cookie - i have errors implementing this) to having a custom nextjs route handler (and custom collection endpoint) that requests to the company’s auth api then authorizing the response with the appropriate headers (much like what the payload’s login does but just have an extra check)



2nd approach seems to be working fine but when the app automatically requests GET “/api/users/me”, the user is always null





Anyone here who have experieced the same? I was looking at payload’s source code and I have thought

  • default discord avatar
    ithomanlast year

    Can you provide a little more info, are you using oAuth or another approach fro the actual authentication, can you share your custom strategy code?

  • default discord avatar
    jomelorskieelast year

    Hey thanks for the reply,



    As of now I’m not using any strategies and instead sticked on the route handler option…




    So I have this route (custom/login/route.ts) thay resides adjacently with (payload) folder



    Here’s the code I’ve got:



    https://pastebin.com/sawJsm6T

    I also customized the login form to make it call that route in submit

  • default discord avatar
    ithomanlast year

    So I used custom strategies and was succsefull can I ask why you abandoned that you did mention using it.



    The login form can be replaced, if needs be.

  • default discord avatar
    jomelorskieelast year

    I abandoned it because I was having issues while authenticating the user (maybe I’ve done something wrong in the config, I dunno 🤣)

  • default discord avatar
    ithomanlast year

    In my approach, I replaced the login form, and took over everything, then used a custom strategy to get it back into payload.



    Actually was easier then I thought.

  • default discord avatar
    jomelorskieelast year

    Do you have a minimal copy of your setup?



    I was really confused about how custom strategies works lol

  • default discord avatar
    ithomanlast year

    I can probably get something together for you in fack I can share most of it because, in my case it's just Google Auth so ... nothing propritary.




    May take me a few posts to comunicate it all.

  • default discord avatar
    jomelorskieelast year

    All good! Thank you! You’re God sent!!

  • default discord avatar
    ithomanlast year

    Step #1 (Custom Login Form)



    First I crated a custom Login form and set up my system to use it. This is a two part action because you can't just replace the login form as you would think you can you must first replace it and then setup a custom route to it...



    So this was the key bits of my config:



    export const payloadConfig = buildConfig({


    // ...


    admin: {


    // ...


    routes: {


    login: '/auth/login',


    },


    // ...


    components: {


    // ...


    views: {


    login: {


    Component: '/views/LoginView', // Your path to your login view


    path: '/auth/login',


    },


    // ...


    },


    // ...


    },


    // ...


    },


    // ...


    });



    NOTE: this /auth/... route is OUT SIDE of Payload's control. For that I just used app router and setup my own Next.js route.



    Now that directs the use back to a custom endpoint I setup.



    I'll note again I created app/auth to handle all routes for this path so this is just a normal Next.js route at this point.



    This really just does some basic security validations, set's a state cookie (CSRF protection) and performs a redirect to Google Auth. I didn't have to direct here I could have gone straight to google but this give me the opportunity to validate a few things.




    Also as my app is multi-tenanted it was helpful for me to be able to compute the redirect URL.



    I don't know your auth system so this may be completely unnecessary for you.



    This is an earlier version so you will some some of the safeguard code is commented out.



    File is located at /app/auth/google/route.ts



    Of course this is oAuth so I'm expecting a callback that bring us to:



    /app/auth/google/callback/route.ts



    This is just good old code auth taking a code in the callback and going back to the IDP to validate.



    Your system would do somethign different but the key here was setting the cookie:



    // Set the JWT in an HTTP-only cookie


    const jwtCookie = serialize(

    ${process.env.COOKIE_PREFIX}-token

    , token, {


    httpOnly: true,


    secure: isSecure(request),


    maxAge: 60 * 60, // 1 hour


    path: "/",


    sameSite: "lax",


    });




    This is what I use in my strategy.



    Now we get to the strategy part...



    This is my collection config that is my User's collection



    Here's the important parts.



    NOTE in my case I validate that they are with my company and not "any other google workspace" that's an extra check because I have google setup to only allow my domain usage, but when I turn on multi-tenant I'll need to validate against the "approved" list. So this check is useful for me but may be less so for you. You may want to do other checks.



    First I crate a new field to hold the

    sub

    returned from oAuth. (any other IDP provided user identifier would also work). This field can then be used to find my user (we want to pull the user from our User's collection).



    My user's collection is really just a simple wrapper over "oatuh email profile" scopes so not that complex.



    In the google strategy I read (and of course validate) the token (I set the token myself so I can now validate it). Create a where clause to pull the user record out of the DB and return that to payload.



    BUT NOTE:



    If you don't also return the collection it WILL not work. That took me HOURS to figure out because I missed it and well it just doesn't work and you don't get an error.



    That should get you started, let me know how it progresses for you. I can probably walk you through more when you have some results.

  • default discord avatar
    jomelorskieelast year

    I’ll try these, thank you so much

    @835935135815041075

    !!!

  • default discord avatar
    ithomanlast year

    Sure thing reach back out when (you always do when doing something new with someone elses untested code right) run into problems.



    If you can simplify your logic to setting a token like I did the strategy should be what you were missing.

  • default discord avatar
    jomelorskieelast year

    Hey

    @835935135815041075

    I’ve done exactly what you mentioned but payload doesn’t seem to execute the authenticate function in the strategies?



    Giving the same result I had with what I previously implemented



    I’d done it!!! Thank you for your help mate

    @835935135815041075

    , I’d be sharing an article and sample project using my approach soon!



    Your ideas played a big role for figuring this out!!

  • default discord avatar
    ithomanlast year

    Love to hear more about what you changed.



    It helps to have a working same that you know must work because it works for someone so you can figure out your differences until it works for you.

  • default discord avatar
    drmandelbrotlast year

    Hi ! What strategy did you finally used? The authenticate function is not working for me either.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.