FusionAuth
    • Home
    • Categories
    • Recent
    • Popular
    • Pricing
    • Contact us
    • Docs
    • Login
    1. Home
    2. naughtly.keller
    N
    • Profile
    • Following 2
    • Followers 0
    • Topics 2
    • Posts 10
    • Best 5
    • Controversial 0
    • Groups 0

    naughtly.keller

    @naughtly.keller

    5
    Reputation
    10
    Profile views
    10
    Posts
    0
    Followers
    2
    Following
    Joined Last Online

    naughtly.keller Unfollow Follow

    Best posts made by naughtly.keller

    • RE: Passwordless registration

      I think the answer is in the docs.

      When FusionAuth is your user datastore, adding a user means you must either provide a password or send them a link to set up their initial password.

      If you are only allowing passwordless authentication for your application, donโ€™t allow the user to specify a password and instead generate a random series of characters for the password. We recommend generating at least 32 characters in the ascii character set that are completely random to ensure the userโ€™s account is secure.

      posted in Q&A
      N
      naughtly.keller
    • FusionAuth + NextAuth refresh tokens

      I'm new to FusionAuth. I came to know about it because of NextAuth and I love it! Now I'm looking to build a boilerplate app as my go to full-stack platform: Next.js + NextAuth + FusionAuth + Hasura.

      My only issue so far is how to implement refresh tokens. NextAuth provides a demo for Google as OAuth provider, but I couldn't find anything inside FusionAuth Docs that would help me. Any hints please?

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      @dan I thought the difficulty was subjective, due to my inexperience with FusionAuth, but I can write down a tutorial and push a demo if you like ๐Ÿ™‚

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      Hey @sander Can you be more precise about how you want to use organizations? Do you mean implementing some sort of multi-tenancy? I'd be happy to collaborate ๐Ÿ™‚

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      Hey @sander your issues seem to be related more with how Hasura's authorization system works than FusionAuth authentication. However, you can populate your JWT with the values you need. As @dan suggested, I would probably use Groups to model organizations, then it's easy to add the relative claims on the access token. So yes, you can populate your token with claims for both a set of roles and one or more organizations. Everything else should be in the authorization system domain, and considering you are using Hasura you can probably model those relationships in the database.

      posted in Q&A
      N
      naughtly.keller

    Latest posts made by naughtly.keller

    • Support for alternative search engines

      I'm struggling to define decent initial requirements to start up FusionAuth in production, with most of my problems regarding the deployment of an ES cluster. If it wasn't for ES, FusionAuth would be easy to start with, however I won't even consider switching to DB search, as search capabilities are too basic. Honestly, with thousands config options, ES looks way more complex and resource intensive than FusionAuth itself, so I wonder if a simpler alternative, like Typesense or Meilisearch could be supported in addition.

      Finally, although I understand that system requirements can vary wildly based on use case, it would be great to have some direction, with minimum requirements to get started for a small reliable production installation of FusionAuth + ES.

      posted in General Discussion
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      Hey @sander your issues seem to be related more with how Hasura's authorization system works than FusionAuth authentication. However, you can populate your JWT with the values you need. As @dan suggested, I would probably use Groups to model organizations, then it's easy to add the relative claims on the access token. So yes, you can populate your token with claims for both a set of roles and one or more organizations. Everything else should be in the authorization system domain, and considering you are using Hasura you can probably model those relationships in the database.

      posted in Q&A
      N
      naughtly.keller
    • RE: advice for multi tenant single SaaS app.

      I guess this has more to do with Hasura's authorization system than FusionAuth authentication. However, as for FusionAuth, I think you can use Groups to model organizations and then populate your access token with claims based on the actual memberships your users have. You can additionally model roles with FusionAuth, but if you need to switch back and forth between them, you'd probably want to model those relationship in your database.

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      Hey @sander Can you be more precise about how you want to use organizations? Do you mean implementing some sort of multi-tenancy? I'd be happy to collaborate ๐Ÿ™‚

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      @dan I thought the difficulty was subjective, due to my inexperience with FusionAuth, but I can write down a tutorial and push a demo if you like ๐Ÿ™‚

      posted in Q&A
      N
      naughtly.keller
    • RE: Passwordless registration

      I think the answer is in the docs.

      When FusionAuth is your user datastore, adding a user means you must either provide a password or send them a link to set up their initial password.

      If you are only allowing passwordless authentication for your application, donโ€™t allow the user to specify a password and instead generate a random series of characters for the password. We recommend generating at least 32 characters in the ascii character set that are completely random to ensure the userโ€™s account is secure.

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      Hey @joshua ,
      After complicating my life in a number of painful ways (please, check above) ๐Ÿ™„โ˜๏ธ which was still worthy for my learning journey, I ended up following all your advices FTW:

      • Using lambdas resulted in a much cleaner and faster implementation;
      • You can also get away without lambdas as well (look ma, no lambdas): all you need to do is map the available access token claims to those required by hasura;
      • You need no extra RSA keys and thanks to FusionAuth you don't even need to pass a public key to hasura: all you need is set the jwk_url parameter.

      At the end of the day, the correct implementation was so smooth I doubt it will need a tutorial ๐Ÿค”

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      Hey @joshua thank you so much ๐Ÿ™
      I spent the weekend on it, and I have been successful. Honestly, FusionAuth has been a revelation. It's extremely powerful, and because of that I struggled a bit getting to know all the features. I apologize for my previous questions... They sound a bit silly now.

      I was not yet aware of both the userinfo and introspect apis, so thanks again for letting me know about them. I like the userinfo api more, although introspect does return all the claims, including iat and exp. But before I get into it, please let me describe what I did. I'm no security expert, and I'd be happy if you could vet the process at a high level to make sure I'm not doing anything blatantly naive. Once I complete my implementation, I plan to write a tutorial about Next.js + FusionAuth + Hasura.

      After signing in, I grab the accessToken prop and very manually run it through jsonwebtoken.verify using the public key stored on FusionAuth and hold a reference to that object. I then add to it Hasura's custom claims, and then sign this thing using a different RSA key, known by the Hasura server. When it's time to refresh the token I simply repeat the process: decoding the token, enhancing it with custom claims and signing it again. The resulting access token is stored in session and used to talk to the server.

      The next step would be trying to implement the userinfo verification api you suggested instead of manually verifying the token.

      I have a couple of questions now, which I hope you can answer:

      • You mentioned both iat and exp are reserved. I currently use them in my enhanced token to let hasura know when it's time to expire the token. As of my current understanding, every newly signed token would have at least a new iat set. What do you think I should use to set exp? Maybe the account.expires_in prop I get from FusionAuth?
      • The sign in process right now requires to call FusionAuth, then I would have to hit the userinfo endpoint and finally call hasura with an upsert operation in case of a new user. Wouldn't that be too chatty and slow? Would you suggest a different flow?
      • I'm currently using 2 different key pairs in this process: the FusionAuth's application RSA256 key for the login process, and an RSA512 key to sign/verify the final access token I send to hasura. Should I just use one key? Having FusionAuth manage keys would be great, but how can I use a key managed by FusionAuth to sign a token from the outside? I wasn't able to retrieve the private key or find an api for that.
      • Finally, is it possible to rotate keys automatically in FusionAuth like Firebase does for example?

      I apologize for the long winded post and number of questions. Thank you very much for your time and kind support!

      posted in Q&A
      N
      naughtly.keller
    • RE: FusionAuth + NextAuth refresh tokens

      I think I had some success so far. I was able to hit the right endpoint, found here after all. Below is the code, however I still have to implement the token refresh logic. I will update the code when I'm done. At this point I have another question though:

      In order to enhance NextAuth token with required Hasura custom claims, I need to set a new iat and exp value. These values are passed to NextAuth by FusionAuth in the account.accessToken property on the jwt callback event. Is there a way and is it safe to decode and grab all values from account.accessToken? It looks like it contains exactly all props I need, together with exact iat and exp.

      // [...nextauth].js api route
      
      import {cleanEnv, host, str} from 'envalid'
      import jwt from 'jsonwebtoken'
      import NextAuth from 'next-auth'
      import Providers from 'next-auth/providers'
      
      const env = cleanEnv(process.env, {
        FUSIONAUTH_DOMAIN: host(),
        FUSIONAUTH_CLIENT_ID: str(),
        FUSIONAUTH_SECRET: str(),
        FUSIONAUTH_TENANT_ID: str(),
        SECRET: str(),
      })
      
      const FUSIONAUTH_REFRESH_TOKEN_URL = `${FUSIONAUTH_DOMAIN}/oauth2/token?`
      
      async function refreshAccessToken(token) {
        try {
          const url =
            FUSIONAUTH_REFRESH_TOKEN_URL +
            new URLSearchParams({
              client_id: env.FUSIONAUTH_CLIENT_ID,
              client_secret: env.FUSIONAUTH_SECRET,
              tenant_id: env.FUSIONAUTH_TENANT_ID,
              grant_type: "refresh_token",
              refresh_token: token.refreshToken,
            });
      
          const response = await fetch(url, {
            headers: {
              "Content-Type": "application/x-www-form-urlencoded",
            },
            method: "POST",
          });
      
          const refreshedTokens = await response.json();
      
          if (!response.ok) {
            throw refreshedTokens;
          }
      
          return {
            ...token,
            accessToken: refreshedTokens.access_token,
            accessTokenExpires: Date.now() + refreshedTokens.expires_in * 1000,
            refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fall back to old refresh token
          };
        } catch (error) {
          console.log(error);
      
          return {
            ...token,
            error: "RefreshAccessTokenError",
          };
        }
      }
      
      export default NextAuth({
        providers: [
          Providers.FusionAuth({
            id: 'fusionauth',
            name: 'FusionAuth',
            domain: env.FUSIONAUTH_DOMAIN,
            tenantId: env.FUSIONAUTH_TENANT_ID,
            clientId: env.FUSIONAUTH_CLIENT_ID,
            clientSecret: env.FUSIONAUTH_SECRET,
            scope: 'offline_access',
          }),
        ],
      
        secret: env.SECRET,
      
        session: {jwt: true},
      
        jwt: {
          secret: env.SECRET,
          async encode({secret, token}) {
            const jwtClaims = {
              ...token,
              iat: Date.now() / 1000,
              exp: Math.floor(Date.now() / 1000) + 60 * 30,
              'https://hasura.io/jwt/claims': {
                'x-hasura-allowed-roles': token.roles,
                'x-hasura-default-role': 'user',
                'x-hasura-role': 'user',
                'x-hasura-user-id': token.sub,
              },
            }
      
            return jwt.sign(jwtClaims, secret, {algorithm: 'RS512'})
          },
          async decode({secret, token}) {
            return jwt.verify(token, secret, {algorithms: ['RS512']})
          },
        },
      
        pages: {},
      
        callbacks: {
          async jwt(token, user, account, profile) {
            if (user && profile) {
              token.id = user.id
              token.roles = profile.roles
            }
      
            return token
          },
      
          async session(session, token) {
            if (token) {
              const encodedToken = jwt.sign(token, env.SECRET, {algorithm: 'RS512'})
              session.id = token.id
              session.token = encodedToken
              session.error = token.error
            }
      
            return session
          },
        },
      
        events: {},
      })
      
      
      posted in Q&A
      N
      naughtly.keller
    • FusionAuth + NextAuth refresh tokens

      I'm new to FusionAuth. I came to know about it because of NextAuth and I love it! Now I'm looking to build a boilerplate app as my go to full-stack platform: Next.js + NextAuth + FusionAuth + Hasura.

      My only issue so far is how to implement refresh tokens. NextAuth provides a demo for Google as OAuth provider, but I couldn't find anything inside FusionAuth Docs that would help me. Any hints please?

      posted in Q&A
      N
      naughtly.keller