sacsand / gofiber-firebaseauth

Firebase Authentication Middleware for Go Fiber framework.
MIT License
23 stars 8 forks source link

How to Access specific values from claims interface{} #3

Closed Anthonyhawkins closed 2 years ago

Anthonyhawkins commented 3 years ago

This is more likely my lack of understanding of how Go works than a gofiber-firebaseauth specific problem.

In the examples it shows accessing the claims object from context and printing it out.

claims := c.Locals("user")
fmt.Println(claims)

This works and I see this

{false mzeijVVkt6MDFQWmWBgzqr79taq2 ah@gmail.com}

From looking at the source, it loads in the private user struct into the context which is populated by fields from Token from firebase. This results in a generic interface{} for claims and I cannot figure out how to access each field, individually.

I looked into type assertion, reflection etc. but not sure what is needed here.

Thanks for the help.

yasumuo commented 3 years ago

This is more likely my lack of understanding of how Go works than a gofiber-firebaseauth specific problem.

In the examples it shows accessing the claims object from context and printing it out.

claims := c.Locals("user")
fmt.Println(claims)

This works and I see this

{false mzeijVVkt6MDFQWmWBgzqr79taq2 ah@gmail.com}

From looking at the source, it loads in the private user struct into the context which is populated by fields from Token from firebase. This results in a generic interface{} for claims and I cannot figure out how to access each field, individually.

I looked into type assertion, reflection etc. but not sure what is needed here.

Thanks for the help.

I was struggling with a similar problem (I'm also new to Go and still learning).

In my case, I wanted to use the value of the email field, and after a lot of research, I was able to get it by using reflection. The following is the code that solved my case. (I'm running recover to deal with the panic)

defer func() error {
            err := recover()
            if err != nil {
                log.Println("Recover!: ", err)
            }
            return nil
        }()

fu := c.Locals("user")
rfuv := reflect.ValueOf(fu)
rfuv2 := reflect.New(rfuv.Type()).Elem()
rfuv2.Set(rfuv)
rfuv = rfuv2.FieldByName("email")
rfuv = reflect.NewAt(rfuv.Type(), unsafe.Pointer(rfuv.UnsafeAddr())).Elem()
fuvstrptr := (*string)(unsafe.Pointer(rfuv.UnsafeAddr()))
fuvstr := *fuvstrptr

log.Println("User Email: ", fuvstr)

I don't think it's a good solution, and I too would like to have something to access each field :sweat_smile:

sacsand commented 2 years ago

Hi sorry for late reply. some-reason i didn't see this open issue.

You can try below method to access the context param 'user' and attribute values


type user struct{
    emailVerified bool
    userID, email string
}

func authController() fiber.Handler {
    return func(c *fiber.Ctx) error {

        currentUserInBytes := c.Locals("user").([]byte)

        var currentUser = new(user)
        err := json.Unmarshal(currentUserByte, &currentUser)
        if err != nil {
            return err
        }
        fmt.Println(currentUser)
        fmt.Println(currentUser.email)
        return nil

    }
}

thanks!

Anthonyhawkins commented 2 years ago

Ah got it. Thanks for the help.