Python

FlaskでGoogle OAuthを実装する方法

こんにちは、

InfraAcademyというインフラ学習サービスを運営しております、ryuと申します。

今回の記事では、FlaskでGoogle OAuthを実装する方法について解説したいと思います。

OAuthとは、「Open Authorization」の略で、サードパーティのアプリケーションがユーザーの代わりにウェブサービスにアクセスするです。

つまり、Googleのアカウントを使って、アプリケーションにログインできるようになるための実装です。Pythonのコードを含めて詳しく解説します。

関連【おすすめ】コマンドを打ちながらLinuxが学べるサイトInfraAcademy

サーバー構築を実践で身につけるInfraAcademy

※本ページには、プロモーション・アフィリエイトリンクが含まれています

FlaskでGoogle OAuthを実装する方法

Google OAuthを実装する方法は、以下の手順で進めます。

  • Authlibのインストール
  • Google API ConsoleでOAuth 2.0クライアントIDを作成
  • ユーザーモデルの修正
  • Flaskアプリの設定
  • Googleログインルートの追加
  • HTMLの修正

1.Authlibのインストール

まず、パッケージのAuthlibのインストールを行います。Google Oauthを実現するためのパッケージはいくつかありますが、AuthlibはGoogleに限らず、GithubなどのOauthも簡単に実装することが可能です。

以下のコマンドを実行して、インストールします。

pip install authlib

Authlibについてのドキュメントはこちらです。詳細を知りたい方はご覧ください。

https://docs.authlib.org/en/latest

2.Google API ConsoleでOAuth 2.0クライアントIDを作成

次にGoogle API ConsoleでOAuth2.0のクライアントIDを作成します。

コンソール画面に移動したら、「Oauth同意画面」へ移動します。

User Typeは「External」を選択します。

作成をクリックすると、アプリの情報を登録する画面へ移動します。ここで、アプリの情報を入力します。

・アプリ名・サポートメール・アプリケーションのホームページ・認証済みドメイン・ディベロッパーの連絡先の項目を入力します。

アプリのURLがない(開発環境)の方は仮で入力しておきましょう。

次に、「スコープを追加または削除」をクリックします。

基本的には、全てにチェックをいれて更新をクリックします。

残りの設定はそのまま進めます。

次に、認証情報から「+認証情報を作成」をクリックします。

OAuth クライアントID」をクリックします。

次に、Oauthの名前とURIを設定します。

承認済みのJavascript生成元には、アプリのURLを入力します。以下の例では、本番環境のURLと開発環境のURLを2つ指定しています。

リダイレクトURIには、URLの後ろに/auth/callbackをつけます。

これで完了です。

保存をクリックすると、クライアントIDとクライアントシークレットが表示されるのでメモしておきましょう。

3.ユーザーモデルの作成

続いて、ユーザーモデルを作成します。ユーザーモデルはapp.pyかmodels.pyに記述します。

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    email = db.Column(db.String(150), unique=True, nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

Flaskアプリの設定

続いて、Flaskアプリの設定を行います。app.pyなどに記述しましょう。

from authlib.integrations.flask_client import OAuth
from authlib.integrations.base_client.errors import OAuthError

app.config['GOOGLE_CLIENT_ID'] = [クライアントID]
app.config['GOOGLE_CLIENT_SECRET'] = [クライアントシークレット]

oauth = OAuth(app)
google = oauth.register(
    name='google',
    client_id=app.config['GOOGLE_CLIENT_ID'],
    client_secret=app.config['GOOGLE_CLIENT_SECRET'],
    client_kwargs={'scope': 'openid profile email'},
    server_metadata_url='https://accounts.google.com/.well-known/openid-configuration'
)

ログインルートの追加

続いて、ログインルートの追加を行います。ログインページとGoogleのログイン画面が表示されるようにします。

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and user.verify_password(form.password.data):
            login_user(user)
            return redirect(url_for('dashboard'))
        else:
            flash(_('Login Unsuccessful. Please check email and password'), 'danger')
    return render_template('login.html', form=form)

@app.route('/login/google')
def google_login():
    redirect_uri = url_for('google_auth_callback', _external=True)
    return google.authorize_redirect(redirect_uri, prompt='select_account')

@app.route('/auth/callback')
def google_auth_callback():
    try:
        token = google.authorize_access_token()
        resp = google.get('https://www.googleapis.com/oauth2/v1/userinfo', token=token)
        user_info = resp.json()
        email = user_info['email']

        user = User.query.filter_by(email=email).first()
        if user is None:
            user = User(
                email=email, 
                username=user_info['name'],
                password_hash=generate_password_hash('default_password')  
            )
            db.session.add(user)
            db.session.commit()

        login_user(user)
        return redirect(url_for('dashboard'))
    except OAuthError as error:
        flash(f'Authentication failed: {error.description}', 'danger')
        return redirect(url_for('login'))

上記の例では、/loginにアクセスすると、ログインページが表示されます。ログインページには、LoginFormを表示して、ログインに必要な情報を入力させますが、今回のGoogle Oauthにおいては不要です。不必要な方はLoginForm周りを削除してください。

HTMLの修正

最後にHTMLの修正を行います。Google Oauthをログインページに載せたいので、ログインページのHTMLに以下を追加します。

<a href="{{ url_for('google_login') }}">
    Googleでログイン
 </a>

ログインページで、上記のリンクをクリックすると、google_login()関数が実行され、Googleのログインページが表示されます。

以上で設定は完了です。

まとめ

今回の記事では、FlaskでGoogle OAuthを実装する方法について解説しました。

Webアプリでは、Googleアカウントでログインできると、ユーザーはスムーズにアプリを使うことができます。アプリの使いやすさ向上のためにも、OAuthの導入を検討してみましょう。

当ブログでは、このようなITに関する記事を発信しているので興味のある方は引き続きごらんください。

ABOUT ME
ryu@InfraAcademyというインフラ学習サービス運営
InfraAcademyというインフラエンジニア向けの学習サービスを運営しております。 インフラエンジニアからフルスタックエンジニア、PdM サーバ、ネットワーク、セキュリティ、クラウドについて投稿します。
RELATED POST