如何在使用 Supabase Auth 时通过 Google 登录时添加额外的用户元数据?

huangapple go评论52阅读模式
英文:

How to add additional user metadata upon login with Google using Supabase Auth?

问题

我想从已登录用户的 Google 档案中获取名字和姓氏。经过查询,Google 使用 givenNamefamilyName。只使用 Supabase 是否可能实现这一点,还是需要在获取访问令牌后使用 Google API?Supabase 文档中提到,但我不确定如何操作,因为我还没有使用过 Google API。

我已阅读了 Google API 文档 并注意到它将在下个月被弃用,所以我想知道未来最佳方法是什么。

我正在使用 Nuxt 3 的 Supabase 模块:

const supabase = useSupabaseClient();
const accessToken = ref('');

const loginWithGoogle = async () => {
  try {
    const { data, error } = await supabase.auth.signInWithOAuth({
      provider: "google",
      options: {
        redirectTo: "http://localhost:3000/app/home",
        scopes: "openid profile email",
      },
    });
    if (error) throw error;
    accessToken.value = data.session.provider_token;
  } catch (error) {
    console.log("Error logging in with Google: ", error);
  }
};

我遵循了他们的用户管理入门指南,使用 handle_new_user 函数处理用户登录后的用户元数据:

begin
  insert into public.profiles (id, full_name, first_name, last_name, username, avatar_url)
  values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'first_name', new.raw_user_meta_data->>'last_name', new.raw_user_meta_data->>'username', new.raw_user_meta_data->>'avatar_url');
  return new;
end;
英文:

I would like to get the first name and last name from the logged in user's Google profile. Upon checking, Google is using givenName and familyName. Is it possible to only do this with Supabase alone or will I need to use the Google API for this after getting the access token? It says on the Supabase docs but I'm not sure how to do this since I haven't used the Google API as of yet.

I have read the Google API docs and saw it is going to be deprecated next month so I would like to know what is the best approach for this moving forward.

I'm using the Supabase module for Nuxt 3:

const supabase = useSupabaseClient();
const accessToken = ref('');

const loginWithGoogle = async () => {
  try {
    const { data, error } = await supabase.auth.signInWithOAuth({
      provider: "google",
      options: {
        redirectTo: "http://localhost:3000/app/home",
        scopes: "openid profile email",
      },
    });
    if (error) throw error;
    accessToken.value = data.session.provider_token;
  } catch (error) {
    console.log("Error logging in with Google: ", error);
  }
};

I followed their User Management Starter to handle the user metadata upon login using the handle_new_user function:

begin
  insert into public.profiles (id, full_name, first_name, last_name, username, avatar_url)
  values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'first_name', new.raw_user_meta_data->>'last_name', new.raw_user_meta_data->>'username', new.raw_user_meta_data->>'avatar_url');
  return new;
end;

答案1

得分: 2

无法返回翻译结果,请问还有其他什么可以帮到您的吗?

英文:

It seems to me that you can achieve this with Supabase alone, but it's an undocumented feature right now.

For the time being, you can (nearly) achieve what you want with Supabase. Actually, you already have achieved it, as good as it gets with current Supabase features, in your current handle_new_user function:

> I followed their User Management Starter to handle the user metadata upon login using the handle_new_user function

This function makes the full name metadata transferred from Google Accounts available to you in column public.profiles.full_name. First and last name are not available individually, though. (Side note: a good explanation of the details how this handle_new_user trigger function works is this article.)

Why your existing solution is as good as it gets with current Supabase

This kind of metadata transfer is handled in the Supabase gotrue project in the gotrue/api/provider/*.go files. Compare for example gotrue issue #127, where they extended the metadata transferred from Twitter and Github.

Now when you look at google.go l. 68, you see currently two pieces of user metadata are transferred for a login with Google:

data := &UserProvidedData{
    Metadata: map[string]string{
	    nameKey:      u.Name,
		avatarURLKey: u.AvatarURL,
	},
}

nameKey and avatarURLKey are defined in provider.go like this:

const (
	userNameKey  = "user_name"
	avatarURLKey = "avatar_url"
	nameKey      = "full_name"
	aliasKey     = "slug"
)

So these are the same JSON field names used in your existing handle_new_user function, which transfers metadata to your public.profiles table.

Alternative solutions

The downside of the solution above, for your usecase, is that first_name and last_name are not provided, only full_name. This leaves you with four options in total:

  1. Work with only the full name. This would be my preferred solution, as not everyone has a firstname and lastname anyway. Plus, if your software always uses firstname and lastname together anyway, then it does not need to know about any potential sub-structuring of a full name.

  2. Split full_name yourself into first and last name. This could be achieved with a modification to the handle_new_user function. See here how to approach this in PostgreSQL. But really, it's better to work with the full name, as automatic splitting will always make mistakes.

  3. Extend Supabase. If you are self-hosting Supabase for your software, you can make the necessary adaptations to their gotrue component so that more metadata is delivered from a Google user on login. Supabase is open source after all. You can also provide your changes in a pull request back to Supabase and hope they will include them into the official version, but this is not guaranteed of course.

  4. Use the Google API Google Identity Services for Web yourself to get givenName and familyName.

huangapple
  • 本文由 发表于 2023年2月19日 13:54:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75498265.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定