$30 off During Our Annual Pro Sale. View Details »

CLIでOAuth/OIDCを快適に利用する

 CLIでOAuth/OIDCを快適に利用する

Gopher Dojo #2
2018.07.09

Hidetake Iwata

July 09, 2018
Tweet

More Decks by Hidetake Iwata

Other Decks in Technology

Transcript

  1. CLIでOAuth/OIDCを
    快適に利用する
    Hidetake Iwata (@int128)

    View Slide

  2. TL;DR
    CLI(コマンドラインツール)でOAuthやOpenID Connectを利用する場合、
    ユーザは複雑なオペレーションが必要になる
    一時的にHTTPサーバを立ち上げて認可コードを受け取ることで、
    ユーザのオペレーションを軽減できる

    View Slide

  3. Hidetake Iwata
    https://github.com/int128
    Software Engineer at Tokyo ❤ DevOps, Agile, CI/CD, Kubernetes, App Engine, Golang, Gradle, Groovy

    View Slide

  4. CLIでOAuthやOpenID Connectを利用する場合、ユーザは複雑なオペレーションが必
    要になる
    1. ターミナルでコマンドを実行する
    2. ターミナルに表示されたURLをブラウザで開く
    3. Googleアカウントでログインする
    4. ブラウザに表示された認可コードをコピーする
    5. ターミナルに認可コードをペーストする
    6. コマンドの実行結果を見る
    OAuth/OIDC CLIの課題
    https://developers.google.com/identity/protocols/OAuth2#installed

    View Slide

  5. OAuth/OIDC CLIの例
    $ ./upload_google_drive
    Open https://accounts.google.com/…
    Enter code: XXXXXXXXXXX...
    OK.
    You are logged in as int128.






    View Slide

  6. Package golang.org/x/oauth2
    config := &oauth2.Config{
    ClientID: clientID,
    ClientSecret: clientSecret,
    Endpoint: google.Endpoint,
    RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
    }
    authCodeURL := config.AuthCodeURL(state)
    fmt.Printf("Open %s\nEnter code: ", authCodeURL)
    var code string
    _, err := fmt.Scanln(&code)
    token, err := config.Exchange(ctx, code)


    View Slide

  7. OAuth/OIDC CLIのUX改善
    ユーザのオペレーションを以下のように軽減したい
    1. ターミナルでコマンドを実行する
    2. ターミナルに表示されたURLをブラウザで開く
    3. Googleアカウントでログインする
    4. ブラウザに表示された認可コードをコピーする
    5. ターミナルに認可コードをペーストする
    6. コマンドの実行結果を見る

    View Slide

  8. OAuth/OIDC CLIのUX改善
    ユーザのオペレーションを以下のように軽減したい
    1. ターミナルでコマンドを実行する
    2. (外部コマンドで自動的にブラウザを開く)
    3. Googleアカウントでログインする
    4. (ローカルHTTPサーバにリダイレクトされる)
    5. (ローカルHTTPサーバが認可コードを受け取る)
    6. コマンドの実行結果を見る

    View Slide

  9. ブラウザベースの認可コードフロー
    [1] https://developers.google.com/identity/protocols/OAuth2#webserver
    一般的なWebアプリケーションと同様にリダイレクト
    で認可コードを受け取る
    1. HTTPサーバを実行する
    2. ブラウザで認可要求URLを開く
    3. http://localhost へのリダイレクトで認可コード
    を受け取る
    4. HTTPサーバを終了する
    5. 認可コードとトークンを交換する

    View Slide

  10. codeCh := make(chan string)
    errCh := make(chan error)
    server := http.Server{":8080", &AuthCodeGrantHandler{
    Callback: func(code string, err error) {
    switch {
    case err != nil: errCh <- err
    default: codeCh <- code
    }
    }
    }}
    go func() {
    if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
    errCh <- err
    }
    }()
    select {
    case err := <-errCh:
    server.Shutdown(ctx)
    return "", err
    case code := <-codeCh:
    server.Shutdown(ctx)
    return code, nil
    }
    HTTPサーバが認可コードを受け取っ
    たらチャネルに送信
    ゴルーチンでHTTPサーバを実行
    認可コードを受け取ったらHTTPサー
    バをシャットダウン

    View Slide

  11. See Also
    特定URLへのアクセスを契機としたHTTPサーバのGraceful Shutdown
    https://int128.hatenablog.com/entry/2018/03/28/232810
    gpup: Upload files to your Google Photos with the new Photos Library API
    https://github.com/int128/gpup
    kubelogin: kubectl with OpenID Connect authentication
    https://github.com/int128/kubelogin

    View Slide

  12. まとめ
    コマンドラインツールでOAuthやOpenID Connectを利用する場合、
    ユーザは認可コードの貼り付けなどの複雑なオペレーションが必要になる
    一時的にHTTPサーバを立ち上げてリダイレクトで認可コードを受け取ることで、ユーザ
    のオペレーションを軽減できる
    GoのHTTPサーバ、チャネルやゴルーチンを組み合わせた実装を紹介した

    View Slide