gosupabasesupabase-go

Unable to register user in Supabase with golang package github.com/supabase-community/supabase-go


I have been trying to Register a new user using github.com/supabase-community/supabase-go. However I keep getting an error when I try create the user with `AdminCreateUser``

session, err := r.supabaseClient.Auth.AdminCreateUser(types.AdminCreateUserRequest{
        Aud:          "",
        Role:         "authenticated",
        Email:        email,
        Phone:        "",
        Password:     &password,
        EmailConfirm: false,
        PhoneConfirm: false,
        UserMetadata: userMetadata,
        AppMetadata:  nil,
    })

This returns the following error.

response status code 401: {"code":401,"error_code":"no_authorization","msg":"This endpoint requires a Bearer token"}

I am 100% sure I am using the correct key. I even recreated them and confirmed it works via curl...

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InF4dGVpd3BvdXRvaWl0ZXlsa2dtIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc0Mjc0OTczMSwiZXhwIjoyMDU4MzI1NzMxfQ.dECuiB00A07KJxHoP4ugQxfU_u5gTJUxewYmrh356ho" \
  -H "apikey: eyJhbGciOiJIUzI1NiI...sImlhdCI6MTc0Mjc0OTczMSwi..1NzMxfQ.dECuiB00A07KJxHoP4ugQxfU_u5gTJUxewYmrh356ho" \
  -d '{
    "email": "test@gmail.com",
    "password": "password"
  }' \
  "https://qxt...teylkgm.supabase.co/auth/v1/admin/users"
{"id":"089bdf18-d9d9-45e5-92b6-213e7187d356","aud":"authenticated","role":"authenticated","email"

I set up my client like so.

supaClient, err := supabase.NewClient(cfg.SupaBase.SupabaseURL, cfg.SupaBase.SupabaseServiceKey, nil)
if err != nil {
    log.Fatal(err)
}

Which doesn't work except for curl. My cfg.SupaBase.SupabaseKey key allows me to login if the user was already created.

I also tried to manually add the headers with no avail..

options := &supabase.ClientOptions{
    Headers: map[string]string{
        "Authorization": "Bearer " + cfg.SupaBase.SupabaseServiceKey,
        "apikey":        cfg.SupaBase.SupabaseServiceKey,
    },
}

supaClient, err := supabase.NewClient(cfg.SupaBase.SupabaseURL, cfg.SupaBase.SupabaseServiceKey, options)
if err != nil {
    log.Fatal(err)
}

But looking at the source code, it should set the headers correct. Which I can confirm they are because I pulled the project and created a test.

func TestNewClientHeaders(t *testing.T) {
    client, err := supabase.NewClient(API_URL, API_KEY, nil)
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }

    expectedHeaders := map[string]string{
        "Authorization": "Bearer " + API_KEY,
        "apikey":        API_KEY,
    }

    headers := client.GetHeaders()

    if !reflect.DeepEqual(headers, expectedHeaders) {
        t.Errorf("headers do not match, got: %v, want: %v", headers, expectedHeaders)
    }
}

I had to add this method since options was private.

func (c *Client) GetHeaders() map[string]string {
    return c.options.headers
}

Has anyone else had this issue and was able to solve it. I am out of ideas at the moment.


Solution

  • I found a work around. For the client just use the supabase anon key for the client. For admin stuff update the session then try. It worked for me when creating a user.

    s := types.Session{}
    s.AccessToken = <SUPABASE_SERVICE_KEY>
    r.supabaseClient.UpdateAuthSession(s)
    

    Here is the working example snippet.

    func (r *AuthRepository) CreateUser(ctx context.Context, email, password string) (*types.AdminCreateUserResponse, error) {
    
        defaultAvatarURL := r.config.supabase.
        userMetadata := map[string]interface{}{
           "app_metadata": map[string]interface{}{
              "avatar_url": defaultAvatarURL,
           },
        }
    
        // update session with admin token
        s := types.Session{}
        s.AccessToken = cfg.SupaBase.SupabaseServiceKey
        r.supabaseClient.UpdateAuthSession(s)
    
        //TODO: set the Aud
        session, err := r.supabaseClient.Auth.AdminCreateUser(types.AdminCreateUserRequest{
           Aud:          "",
           Role:         "authenticated",
           Email:        email,
           Phone:        "",
           Password:     &password,
           EmailConfirm: false,
           PhoneConfirm: false,
           UserMetadata: userMetadata,
           AppMetadata:  nil,
        })
    
        if err != nil {
           return nil, err
        }
    
        return session, nil
    }
    

    Then my client looks like this.

    supaClient, err := supabase.NewClient(cfg.SupaBase.SupabaseURL, cfg.SupaBase.SupabaseServiceKey, nil)
    if err != nil {
        log.Fatal(err)
    }