DEV Community

Cover image for ເຮົາມາລອງສ້າງ OAuth Facebook ໃນ go ແບບງ່າຍໆ
VONGXAI
VONGXAI

Posted on

ເຮົາມາລອງສ້າງ OAuth Facebook ໃນ go ແບບງ່າຍໆ

ບົດຄວາມນີ້ເຮົາຈະມາລອງສ້າງລະບົບ OAuth Facebook, ສັງເກດເວລາທີ່ເຮົາຈະເຂົ້າໃຊ້ລະບົບລະໃດໜຶ່ງຈະເຫັນວ່າມີປຸ່ມໃຫ້ກົດ Login with Facebook, Login with Google...ຈະເຫັນວ່າມີປຸ່ມໃຫ້ກົດປະມານນີ້, ນັ້ນແຫຼະຄື OAuth ນັ້ນເອງ.

OAuth ຫຼື Open Authentication ເປັນມາດຕະຖານການຢືນຢັນຕົວຕົນ ແລະ ການກວດສອບສິດທິບຸກຄົນອີກຮູບແບບໜຶ່ງໂດຍຕ້ອງໃຫ້ຜູ້ໃຊ້ທຳການຍອມຮັບບາງຢ່າງໃຫ້ Application ເພື່ອເຂົ້າເຖິງຂໍ້ມູນບາງສ່ວນຂອງບຸກຄົນ.

ຂັ້ນຕອນ: ກ່ອນອື່ນໃຫ້ເຮົາໄປທີ່ => https://developers.facebook.com/ ທຳການສະໝັກສະມາຊິກໃຫ້ຮຽບຮ້ອຍຫຼັງຈາກນັ້ນກໍໄປສ້າງແອັບຕາມຂັ້ນຕອນດັ່ງນີ້

1/ ກົດທີ່ MyApps ແລ້ວກົດ CreateApp ດ້ານຂ້ວາມືໃຫ້ເລືອກປະເພດແອັບເປັນ None

Image description

2/ ຕັ້ງຊື່ແອັບ ແລະ ໃສ່ອີເມວໃຫ້ຮຽບຮ້ອຍກົດສ້າງໄດ້ເລີຍ

Image description

3/ ຫຼັງຈາກທີ່ເຮົາສ້າງແອັບສຳເລັດແລ້ວເຮົາຈະໄດ້ key: App ID, App secret ເຮົາຈະເອົາໄປໃສ່ຕອນທີ່ເຮົາສ້າງ API ເປັນ config parameter

Image description

4/ ໄປຕັ້ງຄ່າ Platform ໃນທີ່ນີ້ເຮົາຈະທົດລອງຢູ່ Web browser ໃຫ້ໄປທີ່ Settings->Basic ເລືອນລົງມາທາງລຸ່ມແລ້ວກົດ Add platform ເລືອກ Website ກົດ Next

Image description

5/ ກຳນົດ Site URL ໃນທີ່ນີ້ເຮົາຈະ dev ຢູ່ local ເຮົາເອງກຳນົດເປັນ http://localhost:8080

Image description

6/ ເມື່ອກຳນົດ Site URL ແລ້ວຖ້າຈະໃສ່ Callback URI ໃຫ້ໃສ່ຢູ່ທີ່ຊ່ອງ Valid OAuth Redirect URIs ຕົວຢ່າງ: http://localhost:8080/callback

Image description

OAuth Facebook Flow

Image description

ຊິອະທິບາຍການເຮັດວຽກຂອງມັນຄາວໆຄື:
1/ ເຮົາຕ້ອງສ້າງ Service ໂຕໜຶ່ງຂຶ້ນມາເມື່ອມີການກົດຍິງເຂົ້າມາ Service ຕົວນີ້ປຶບມັນຈະທຳການ redirect ໄປຫາ https://www.facebook.com/v17.0/dialog/oauth
2/ ເມື່ອເຮົາທຳການ Authorize App Facebook ສຳເລັດແລ້ວ Facebook ຈະທຳການ redirect ກັບມາຫາເຮົາຕາມ Url Callback ທີ່ເຮົາໄດ້ກຳນົດໄວ້, ຕາມດ້ວຍ Query Params code ສົ່ງ key token ກັບມາຫາເຮົາ
3/ ຫລັງຈາກນັ້ນເຮົາຈະເອົາ key token ທີ່ໄດ້ມາຈາກ Facebook ເຮົາກໍນຳເອົາ Implement ລຳດັບທັດໄປຖ້າຕ້ອງການໄປດຶ່ງເອົາຂໍ້ມູນພື້ນຖານຈາກ facebook ເຊັ່ນ: ລະຫັດ,ຊື່,ອີເມວ...ໂດຍທີ່ເຮົາສົ່ງ key token ເພື່ອໄປຂໍທີ່ https://graph.facebook.com/v17.0/oauth/access_token

Image description

ເອົາລ່ະມາຮອດຂັ້ນຕອນເຮົາ Codeding ກັນເລີຍ

1/ ສ້າງ Service Login ຕົວຢ່າງໃນ file main.go

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "net/url"

    "github.com/labstack/echo/v4/middleware"

    "github.com/labstack/echo/v4"
)

const (
    ClientID     = "YOUR_APPID"
    ClientSecret = "YOUR_APP_SECRET"
    RedirectURL  = "YOUR_CALLBACK_URL"
)

const htmlIndex = `<html><body> Logged in with <a href="/login">facebook</a></body></html>`

func handleMain(c echo.Context) error {
    return c.HTML(http.StatusOK, htmlIndex)
}

func handleLogin(c echo.Context) error {
    authURL := "https://www.facebook.com/v17.0/dialog/oauth"
    params := url.Values{}
    params.Set("client_id", ClientID)
    params.Set("redirect_uri", RedirectURL)
    params.Set("response_type", "code")
    params.Set("scope", "email")

    redirectURL := authURL + "?" + params.Encode()
    return c.Redirect(http.StatusTemporaryRedirect, redirectURL)
}

func main() {
    e := echo.New()

    e.Use(
        middleware.RequestID(),
        middleware.Logger(),
        middleware.Recover(),
    )

    e.GET("/", handleMain)
    e.GET("/login", handleLogin)

    fmt.Println("Started running on http://localhost:8080")
    log.Fatal(e.Start(":8080"))
}
Enter fullscreen mode Exit fullscreen mode

ທົດສອບກົດທີ່ລິ້ງ Logged in with facebook

Image description

ຖ້າບໍ່ມີຫາຫຍັງກໍຈະໄດ້ຜົນຫຼັບດັ່ງຮູບລຸ່ມນີ້

Image description

ເມື່ອເຮົາກົດ Continue ສັ່ງເກດເບິ່ງ Url Facebook ຈະທຳການ Redirect ກັບມາ Url ຕາມທີ່ເຮົາກຳນົດ

Image description

2/ ສ້າງ Service Callback ເພື່ອຮອງຮັບເພີ່ມໃນ file main.go

e.GET("/callback", handleCallback)
Enter fullscreen mode Exit fullscreen mode

3/ ເພີ່ມຟັງຊັນ handleCallback ຖ້າເຮັດຖືກຕ້ອງສຳເລັດທຳການ return accessToken ອອກໄປ

func handleCallback(c echo.Context) error {
    code := c.QueryParam("code")
    if code == "" {
        return c.String(http.StatusBadRequest, "Authorization code not found.")
    }

    // Exchange the authorization code for an access token
    tokenURL := "https://graph.facebook.com/v17.0/oauth/access_token"
    params := url.Values{}
    params.Set("client_id", ClientID)
    params.Set("client_secret", ClientSecret)
    params.Set("redirect_uri", RedirectURL)
    params.Set("code", code)

    resp, err := http.PostForm(tokenURL, params)
    if err != nil {
        log.Println("Failed to exchange code for token:", err)
        return c.String(http.StatusInternalServerError, "Failed to exchange code for token.")
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        log.Println("Failed to exchange code for token:", resp.Status)
        return c.String(http.StatusInternalServerError, "Failed to exchange code for token.")
    }

    var tokenResp struct {
        AccessToken string `json:"access_token"`
    }
    dec := json.NewDecoder(resp.Body)
    if err := dec.Decode(&tokenResp); err != nil {
        log.Println("Failed to parse token response:", err)
        return c.String(http.StatusInternalServerError, "Failed to parse token response.")
    }

    return c.JSON(http.StatusOK, echo.Map{
        "accessToken": tokenResp.AccessToken,
    })
}
Enter fullscreen mode Exit fullscreen mode

ກໍຈະໄດ້ accessToken ຕອບຈາກ Facebook ແບບນີ້

Image description

4/ ຫຼັງຈາກທີ່ໄດ້ accessToken ແລ້ວເຮົາກໍນຳເອົາໄປ Get user ເພື່ອເອົາຂໍ້ມູນພື້ນຖານເຊັ່ນ: ລະຫັດ,ຊື່,ອີເມວ ໃຫ້ອັບເດດຟັງຊັນ handleCallback ດັ່ງນີ້

func handleCallback(c echo.Context) error {
    code := c.QueryParam("code")
    if code == "" {
        return c.String(http.StatusBadRequest, "Authorization code not found.")
    }

    // Exchange the authorization code for an access token
    tokenURL := "https://graph.facebook.com/v17.0/oauth/access_token"
    params := url.Values{}
    params.Set("client_id", ClientID)
    params.Set("client_secret", ClientSecret)
    params.Set("redirect_uri", RedirectURL)
    params.Set("code", code)

    resp, err := http.PostForm(tokenURL, params)
    if err != nil {
        log.Println("Failed to exchange code for token:", err)
        return c.String(http.StatusInternalServerError, "Failed to exchange code for token.")
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        log.Println("Failed to exchange code for token:", resp.Status)
        return c.String(http.StatusInternalServerError, "Failed to exchange code for token.")
    }

    var tokenResp struct {
        AccessToken string `json:"access_token"`
    }
    dec := json.NewDecoder(resp.Body)
    if err := dec.Decode(&tokenResp); err != nil {
        log.Println("Failed to parse token response:", err)
        return c.String(http.StatusInternalServerError, "Failed to parse token response.")
    }

    fmt.Println("tokenResp.AccessToken: ", tokenResp.AccessToken)

    userFacebook, err := getUserFacebook(c.Request().Context(), tokenResp.AccessToken)
    if err != nil {
        return c.JSON(http.StatusInternalServerError, err)
    }

    return c.JSON(http.StatusOK, echo.Map{
        "userFacebook": userFacebook,
    })
}
Enter fullscreen mode Exit fullscreen mode

ຸ5/ ເພີ່ມຟັງ getUserFacebook

type UserDetail struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func getUserFacebook(ctx context.Context, token string) (*UserDetail, error) {
    url := "https://graph.facebook.com/me?fields=id,name,email&access_token=" + token
    req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
    if err != nil {
        return nil, fmt.Errorf("failed to create request: %w", err)
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, fmt.Errorf("failed to do request: %w", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
    }

    var user UserDetail
    dec := json.NewDecoder(resp.Body)
    if err := dec.Decode(&user); err != nil {
        return nil, fmt.Errorf("failed to decode response: %w", err)
    }

    return &user, nil
}
Enter fullscreen mode Exit fullscreen mode

ທົດສອບ Login ອີກຄັ້ງກໍຈະໄດ້ຜົນຫຼັບອອກມາແບບນີ້

Image description

ມາຮອດນີ້ຖືກວ່າສຳເລັດແລ້ວ 5555 ສຳລັບການທົດລອງສ້າງ OAuth Facebook ໃນ go Basic ເບື້ອງຕົ້ນກໍຈະມີປະມານນີ້, ມີອັນໃດຜິດພາດບໍ່ຄົບຖ້ວນກະຂໍອະໄພນຳເດີຜູ້ຂຽນເອງກໍຫາເລີ່ມໃຊ້ຄືກັນສາມາດແນະນຳເພີ່ມຕື່ມໄດ້

ຂອບໃຈທີ່ອ່ານຈົບ

Top comments (0)