LoginSignup
5
7

More than 5 years have passed since last update.

go言語でOAuth2認証を実装

Last updated at Posted at 2018-09-06

go言語でOAuth2認証

最近,go言語でGithubとQiitaのOauth2認証を実装することがあったのでメモ書き程度に書いていきます.

OAuth2認証のフロー

OAuth2のフローは以下のようになっています(Githubの場合)

  1. Githubにコードをリクエスト
  2. あらかじめ指定しておいたページに自動でリダイレクト
  3. リダイレクト時にURLにパラメータで渡されたcodeを使ってアクセストークンをリクエスト
  4. 3のレスポンスのbodyからアクセストークンを取得
  5. アクセストークンを使ってAPIを使用

ざっくりと以上のような流れで認証します.

Githubの場合

まず,Githubのアプリに登録します.
そこで得られたClientIDとClientSecretをメモなどして覚えておきましょう.
リダイレクト先のURLは自分のサイトの適当なURLを指定しましょう(例http://自分のサイトURL/oauth/callback)

  1. Githubにコードをリクエスト
  2. あらかじめ指定しておいたページに自動でリダイレクト
  3. リダイレクト時にURLにパラメータで渡されたcodeを使ってアクセストークンをリクエスト
  4. 3のレスポンスのbodyからアクセストークンを取得
  5. アクセストークンを使ってAPIを使用

Githubアプリを登録したらまず,Githubの指定されたURL(https://github.com/login/oauth/authorize) に先ほど取得したClientIDをパラメータに指定してリダイレクトします.
実装は以下のようになります.なお,今回はgo言語のwebフレームワークginを使っています

func RedirectAuthrizeClient(c *gin.Context, clientID string) { 
   authURL := "https://github.com/login/oauth/authorize?client_id=" + clientID
   c.Redirect(http.StatusMovedPermanently, authURL)
}

  1. Githubにコードをリクエスト
  2. あらかじめ指定しておいたページに自動でリダイレクト
  3. リダイレクト時にURLにパラメータで渡されたcodeを使ってアクセストークンをリクエスト
  4. 3のレスポンスのbodyからアクセストークンを取得
  5. アクセストークンを使ってAPIを使用

次にGithubアプリを登録する際に指定したページに自動でリダイレクトされるのでそこでの処理を実装していきます.


type CredentialInfo struct {
    AccessToken string `json:"access_token"`
    Scope      string `json:"scope"`
    TokenType string `json:"token_type"`
}


func GetAccessTokenClient(c *gin.Context, clientID string, clientSecret string) (*CredentialInfo){
    code := c.Request.URL.Query().Get("code")
    state := c.Request.URL.Query().Get("state")
    if state == "" {
        fmt.Println("state is empty")
    }
    values := url.Values{}
    values.Add("code", code)
    values.Add("client_id", clientID)
    values.Add("client_secret", clientSecret)
    req, err := http.NewRequest(
        "POST",
        "https://github.com/login/oauth/access_token",
        strings.NewReader(values.Encode()),
    )
    if err != nil {
        panic(err)
    }

    req.Header.Set("Accept", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    byteArray, _ := ioutil.ReadAll(resp.Body)

    var cre *CredentialInfo
    json.Unmarshal(byteArray, &cre)

    c.Redirect(http.StatusMovedPermanently, "/")
    return
}

req.Header.Set("Accept", "application/json")の部分はレスポンスのbodyの形式を指定していて,これを指定しないとレスポンスがjson形式で返ってきません.Githubでは

{
  access_token: ***,
  scope: ***,
  token_type:"bearer"
}

の形式でレスポンスが返ってくるのでこの中のaccess_tokenを保存したり変数に格納などしてAPIを呼び出すときに使います.

  1. Githubにコードをリクエスト
  2. あらかじめ指定しておいたページに自動でリダイレクト
  3. リダイレクト時にURLにパラメータで渡されたcodeを使ってアクセストークンをリクエスト
  4. 3のレスポンスのbodyからアクセストークンを取得
  5. アクセストークンを使ってAPIを使用

あとは取得したアクセストークンをヘッダに含んでAPIを叩くだけです!

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7