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

Figma as a provider #5841

Closed
eoinf78 opened this issue Nov 18, 2022 · 9 comments
Closed

Figma as a provider #5841

eoinf78 opened this issue Nov 18, 2022 · 9 comments
Labels
enhancement New feature or request good first issue Good issue to take for first time contributors providers stale Did not receive any activity for 60 days

Comments

@eoinf78
Copy link

eoinf78 commented Nov 18, 2022

Description 📓

Figma Design Tool includes a API for developers including OAuth Authentication. It would be good if this could be added as a provider:

Figma API OAuth docs.

How to reproduce ☕️

Attempted to create a custom provider for this (see code below) but have been running into issues with callbacks returning a 403 error when trying to retrieve token. Not sure if this is an issue on Figma's end

import { OAuthConfig, OAuthUserConfig } from "next-auth/providers";

export interface FigmaProfile extends Record<string, any> {
  id: string // this is really a number
  profile: string
}

export default function FigmaProvider<P extends FigmaProfile>(
  options: OAuthUserConfig<P>
): OAuthConfig<P> {
  return {
    id: "figma",
    name: "Figma",
    type: "oauth",
    authorization: {
      url: "https://www.figma.com/oauth",
      params: {
        scope: "file_read",
        response_type: 'code',
      },
    },
    token: {
      url: "https://www.figma.com/api/oauth/token",
      params: {
        grant_type: 'authorization_code',
        client_secret: options.clientSecret
      }
    },
    userinfo: "https://api.figma.com/v1/me",
    profile(profile) {
      return {
        id: profile.id,
        name: `${profile.handle}`,
        email: profile.email,
        image: profile.img_url,
      }
    },
    options,
  }
}

Contributing 🙌🏽

Yes, I am willing to help implement this feature in a PR

@eoinf78 eoinf78 added enhancement New feature or request triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Nov 18, 2022
@eoinf78 eoinf78 changed the title Figma as provider Figma as a provider Nov 18, 2022
@balazsorban44 balazsorban44 added providers good first issue Good issue to take for first time contributors and removed triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Nov 20, 2022
@seanchas116
Copy link

This worked for me. Looks like you need to implement a custom request for token:

const figmaProvider: Provider = {
  id: "figma",
  name: "Figma",
  type: "oauth",
  authorization: {
    url: "https://www.figma.com/oauth",
    params: {
      scope: "file_read",
      response_type: "code",
    },
  },
  token: {
    url: "https://www.figma.com/api/oauth/token",
    async request(context) {
      const provider = context.provider;
      const res = await fetch(
        `https://www.figma.com/api/oauth/token?client_id=${provider.clientId}&client_secret=${provider.clientSecret}&redirect_uri=${provider.callbackUrl}&code=${context.params.code}&grant_type=authorization_code`,
        { method: "POST" }
      );
      const json = await res.json();
      return { tokens: json };
    },
  },
  userinfo: "https://api.figma.com/v1/me",
  profile(profile) {
    return {
      id: profile.id,
      name: `${profile.handle}`,
      email: profile.email,
      image: profile.img_url,
    };
  },
  clientId: process.env.FIGMA_ID,
  clientSecret: process.env.FIGMA_SECRET,
};

@stale
Copy link

stale bot commented Mar 11, 2023

It looks like this issue did not receive any activity for 60 days. It will be closed in 7 days if no further activity occurs. If you think your issue is still relevant, commenting will keep it open. Thanks!

@stale stale bot added the stale Did not receive any activity for 60 days label Mar 11, 2023
@stale
Copy link

stale bot commented Mar 18, 2023

To keep things tidy, we are closing this issue for now. If you think your issue is still relevant, leave a comment and we might reopen it. Thanks!

@stale stale bot closed this as completed Mar 18, 2023
@btn0s
Copy link

btn0s commented Nov 25, 2023

@seanchas116 are you by any chance using this with the Prisma adapter? I've been pulling my hari out trying to get Figma's OAuth response to work with Prisma's schema.

@AriaFantom
Copy link

I want to make it add as in built provider

@davo
Copy link

davo commented Apr 21, 2024

I'm interested on having Figma as a built-in provider as well.

@Akshithpottigari
Copy link

It is not working. Seems like something's changed. Can you update this?

@kradyy
Copy link

kradyy commented Jan 5, 2025

If anyone is still looking for this to work, check out this updated version for OAuth 2.0

import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import { Provider } from "next-auth/providers";

const FigmaProvider: Provider = {
  id: "figma",
  name: "Figma",
  type: "oauth",
  authorization: {
    url: "https://www.figma.com/oauth",
    params: {
      scope: "file_read",
      response_type: "code",
    },
  },
  token: {
    url: "https://api.figma.com/v1/oauth/token",
    async request(context: any) {
      const provider = context.provider;

      // Create Base64-encoded credentials for Basic Auth
      const credentials = Buffer.from(
        `${provider.clientId}:${provider.clientSecret}`
      ).toString("base64");

      // Prepare form data
      const formData = new URLSearchParams({
        redirect_uri: provider.callbackUrl,
        code: context.params.code,
        grant_type: "authorization_code",
        code_verifier: context.params.code_verifier || '',
      });

      const res = await fetch("https://api.figma.com/v1/oauth/token", {
        method: "POST",
        headers: {
          Authorization: `Basic ${credentials}`,
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: formData.toString(),
      });

      const json = await res.json();

      if (!res.ok) {
        throw new Error(`Failed to get token: ${JSON.stringify(json)}`);
      }

      return {
        tokens: {
          access_token: json.access_token,
          refresh_token: json.refresh_token,
          expires_in: json.expires_in,
          token_type: json.token_type || "Bearer",
        },
      };
    },
  },
  userinfo: "https://api.figma.com/v1/me",
  profile(profile) {
    return {
      id: profile.id,
      name: profile.handle || profile.name,
      email: profile.email || null,
      image: profile.img_url || profile.avatar_url,
    };
  },
  clientId: process.env.FIGMA_CLIENT_ID,
  clientSecret: process.env.FIGMA_CLIENT_SECRET,
  checks: ["state"], // Ensure state is checked for CSRF protection
};

export const authOptions = {
  providers: [
    FigmaProvider,
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  pages: {
    signIn: '/login',
  }
};

export const { handlers, signIn, signOut, auth } = NextAuth(authOptions);

Tested with latest next-auth 5.0.0 (Auth.js)

@deifos
Copy link

deifos commented Jan 10, 2025

If anyone is still looking for this to work, check out this updated version for OAuth 2.0

import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import { Provider } from "next-auth/providers";

const FigmaProvider: Provider = {
  id: "figma",
  name: "Figma",
  type: "oauth",
  authorization: {
    url: "https://www.figma.com/oauth",
    params: {
      scope: "file_read",
      response_type: "code",
    },
  },
  token: {
    url: "https://api.figma.com/v1/oauth/token",
    async request(context: any) {
      const provider = context.provider;

      // Create Base64-encoded credentials for Basic Auth
      const credentials = Buffer.from(
        `${provider.clientId}:${provider.clientSecret}`
      ).toString("base64");

      // Prepare form data
      const formData = new URLSearchParams({
        redirect_uri: provider.callbackUrl,
        code: context.params.code,
        grant_type: "authorization_code",
        code_verifier: context.params.code_verifier || '',
      });

      const res = await fetch("https://api.figma.com/v1/oauth/token", {
        method: "POST",
        headers: {
          Authorization: `Basic ${credentials}`,
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: formData.toString(),
      });

      const json = await res.json();

      if (!res.ok) {
        throw new Error(`Failed to get token: ${JSON.stringify(json)}`);
      }

      return {
        tokens: {
          access_token: json.access_token,
          refresh_token: json.refresh_token,
          expires_in: json.expires_in,
          token_type: json.token_type || "Bearer",
        },
      };
    },
  },
  userinfo: "https://api.figma.com/v1/me",
  profile(profile) {
    return {
      id: profile.id,
      name: profile.handle || profile.name,
      email: profile.email || null,
      image: profile.img_url || profile.avatar_url,
    };
  },
  clientId: process.env.FIGMA_CLIENT_ID,
  clientSecret: process.env.FIGMA_CLIENT_SECRET,
  checks: ["state"], // Ensure state is checked for CSRF protection
};

export const authOptions = {
  providers: [
    FigmaProvider,
    Google({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  pages: {
    signIn: '/login',
  }
};

export const { handlers, signIn, signOut, auth } = NextAuth(authOptions);

Tested with latest next-auth 5.0.0 (Auth.js)

Thanks I will test this out on the current app I'm building.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good issue to take for first time contributors providers stale Did not receive any activity for 60 days
Projects
None yet
Development

No branches or pull requests

9 participants