見出し画像

Google Colabでユーザーのメールアドレスを取得

大学の課題としてGoogle Colabを使ったデータ分析レポートを課しているわけですが、それに関して前からやってみたかったこととして、Colabを操作しているGoogleアカウントの情報を取得するというのがあった。メールアドレスの取得に基づいて実現したいことは主に3つ。

  • 本人のアカウントで(最終的には)操作されたことを確認したい

  • セキュリティの観点から大学発行のGoogleアカウントで利用していることを確認したい

  • 分析データを人によって違うものにするため、データ生成時の初期乱数値(seed)を学籍番号にしたい

やってみたら結構簡単だった。

1. 認証情報へのアクセスの許可

まずgoogle.colabのライブラリから authenticate_user (https://github.com/googlecolab/colabtools/blob/main/google/colab/auth.py#L241) で認証をかける。

from google.colab import auth
auth.authenticate_user()

すると以下のようなダイアログが出る。

後ろのコードが若干見えるけど下にも貼ってあるやつなのでOK

こいつを許可すると、こんな感じでウィンドウが開いて諸々許可することになる。

2. アクセストークンの取得

次にユーザー情報を読み出す際に必要なトークンを取得する。これはGoogle Cloudのコマンド`!gcloud auth print-access-token`で手に入るので、

token = !gcloud auth print-access-token

今回はその返り値を`token`としておく。ただ、このトークンはリスト形式で返ってくることに注意。とりあえずは'token[0]'で使えばよい。

3. ユーザー情報の取得

まずはGoogleのOpenID Configuration('https://accounts.google.com/.well-known/openid-configuration')からエンドポイントの一覧を取得してみる。

url  = 'https://accounts.google.com/.well-known/openid-configuration'
ret  = requests.get(url)
endp = ret.json()

いまエンドポイントの一覧を取得したので、そのなかからuserinfo_endpoint('https://openidconnect.googleapis.com/v1/userinfo')にアクセスしてみる。

url = endp['userinfo_endpoint'] + '?access_token=' + token[0]
ret = requests.get(url)
info = ret.json()

print(ret)
info

これは名前のとおりGoogleのユーザーアカウントの基本情報を取ってくるもの。今回はあくまでも学生の課題レポートのための検討なので、ユーザーのプロフィール画像まで取得できちゃうのが個人的にはあまりよくないと思っている。まあメールアドレスに紐づいたアイコン画像なんてほとんど公開情報なんだけど、不要な情報は取得すべきではないという主義なんですよね。

つまり単一の関数にまとめるとこんな感じ。

def get_email_address():
    import requests
    from google.colab import auth

    auth.authenticate_user()
    token = !gcloud auth print-access-token

    openid_url  = 'https://accounts.google.com/.well-known/openid-configuration'
    ret1  = requests.get(openid_url)
    endp = ret1.json() if ret1.status_code==200 else {}

    ret2 = requests.get(endp['userinfo_endpoint']+'?access_token='+token[0])
    info = ret2.json() if ret2.status_code==200 else {}
    return info.get('email')

単一の関数にまとめるにあたっては、エラーが出ると面倒なのでGET投げて上手くいかなかった場合とか、返ってきたJSONに'email'のkeyがなかった場合とかも考えてちょっとだけ変えました。

同一ファイルを共有して複数アカウントで実行してみたところ、常に最後に実行したGoogleアカウントが記録されていた。そういう意味で、不正アクセスあるいは他者にアカウントごと操作してもらっている場合を除けば、一応は本人が操作していることの最低限の保証にはなりそう。

今回はOpenID Configuration経由にしたけど、googleapisのOAuth2 v3のリストの中にも普通にuserinfoやtokeninfoを取得するAPIがあるので、そっちを叩いてもよい。

url1 = 'https://www.googleapis.com/oauth2/v3/userinfo?access_token='+token[0]
url2 = 'https://www.googleapis.com/oauth2/v3/tokeninfo?access_token='+token[0]

ret  = requests.get(url1)
info = ret.json()

tokeninfoに関しては冒頭で取得したトークンに関する情報が取得できる感じですね。だからそのトークンで許可されてるスコープの一覧とか有効期限も出てくる。

4. 他にも

うちの大学では学生のメールアドレスの@以前が学籍番号のみなので、メールアドレスが取得できれば学籍番号も取得できる。だから学籍番号`student_id`を取得して
numpy.random.seed(student_id)
pandas.DataFrame.sample(frac=0.1, random_state=student_id)
とかっていう形で学生によって異なるデータセットを作ることができる。

僕の実習では、僕のGitHubの授業用リポジトリから初期設定用のコードをcloneしてきて自動的に走らせる実習用テンプレートがあるので、そこに上のコードを加えることで諸々できるようになりそう。
ちなみにこのcloneの方法としてはreadonlyのGitHub fine-grained personal access tokensを授業ページに貼っていて、正直あまり良くはないのだけれど、授業用リポジトリ自体そもそもpublicでもいいような内容しか置いてないのでこの方法を取っているという感じですね。

この記事が気に入ったらサポートをしてみませんか?