4
0

公式LINEアカウントへのログイン処理をAWS Lambda経由で実装してみた

Posted at

はじめに

本記事はPERSOL PROCESS & TECHNOLOGY Advent Calendar 2023の記事です。
業務でLINEとAWS実装を経験することがあり、独学ながら実装したお話を書いてみようと思います。といってもLINEの公式ドキュメントがすごく丁寧に教えてくれているので、こんなふうに実装できるんだ〜便利〜とか思ってくれれば良きです。では

背景

今回日本で利用者数が多いSNSであるLINEと、サーバーレスであるAWS Lambdaを利用しています。

LINEは、月間ユーザー数9,500万人(2023年6月末時点)と多くのユーザー数を抱えています。
参照:LINEユーザー層

ともあり、年齢層に関係なく利用ユーザーも多いです。(個人的には思ったより高齢層というのも関係なく高いのに驚き)使いやすくて便利。ですね。

Lambdaはサーバーレスのサービスのため、サーバー運用について考える必要がなく、簡単に実装できます。こちらも使いやすくて便利。です。
ユーザーも使いやすい。(使われやすいともいう。)開発者も開発しやすい。のでこのような構成を選択しています。

構成図

今回はどこかのサイトのユーザーが自環境へ入り、LINEログインのリダイレクトを行います。リダイレクト結果が自環境に戻り、結果をどこかのサイトへ結果を返す、というような処理を実装します。

(今回の事象では認証前後で、Lambda関数による処理が必要なためこのような構成としています。LINE認証を行うのに必ずLamdba関数を通す必要はありません。)

ユーザー視点遷移

ユーザーはどこかのサイトの”LINEID連携”ボタンを押下すると、紐づいている公式LINEアカウントへアクセス権限を"許可する"ボタンを押下、無事にユーザー情報を取得できれば完了!となります。
(ユーザーのLINEアカウントと分けるため本記事では認証されるLINEアカウントを”公式アカウント”と呼んでいます。)

では実際の実装内容に入ります。

事前準備

必要なものは
・LINEDevelopersアカウント
・AWSアカウント
となります。

登録方法は今回省略します。どちらもぽちぽちと簡単に作成できます。

LINE DevelopersではLINE公式チャネルを作成します。

どのアカウントへログインするのかなどを特定するID情報が実装時必要となります。呼び出し時は上記”開発中”→”公開済み”に変更するのを忘れずに!

AWSではLambda関数、APIGatewayを作成します。(権限や設定値等は各自の設計および環境に依存するため、参考程度にお考えください。)

まずはLambda関数です。

作業環境によって1から作成しても、コンテナイメージから作成してどちらでも大丈夫です。
(後日本開発環境のCI/CDに関する記事を投稿予定です→PERSOL PROCESS & TECHNOLOGY Advent Calendar 2023

次にAPIGatewayです。
今回はREST APIを選択しています。

作成したREST APIにリソースを作成して、その中にメソッドを作成します。ここでは先ほど作成したLambda関数と統合したメソッドとなります。
また今回はLambdaプロキシ統合を利用しています。簡単に言えば、リクエストやレスポンスなどAPIGatewayでマッピングしなくても簡単に使えるよ〜というやつです。

作成したAPIはこんな感じです。1つめのAPIのメソッドタイプはGETでもPOSTでもこのAPIを呼び出す先に合わせ選択ください。2つめのAPIメソッドタイプはLINEからのリダイレクトを受信する箇所になるため、"GET"とします。

AWS Lambda実装

1つ目のLamdba関数

1つ目のLambda関数ではAPIを受けてLINEの認可URLを作成し、ユーザーに向けてリダイレクトを実施します。

LINE認可は、LINEとユーザー間で認証と認可のプロセスを行います。
ここでの検討ポイントは”どんなユーザー情報が欲しいのか”ということです。
認可URLのパラメータ”scope”で、どのアクセス権が欲しいのかを指定します。

scope = profile → プロフィール情報(LINEユーザーID、LINE表示名前、LINEアイコンURLなど)
scope = openid → ユーザー識別子(LINEユーザーID、IDトークンの有効期間など)
scope = email → メールアドレス
メールアドレスへのアクセス権が必要な場合は別途LINEDevelopersページよりLINE公式アカウントのメールアドレス取得権限の申請が必要です。

その他必要情報は
・LINEログインチャネルのチャネルID→LINEDevelopersページより、公式アカウントのチャネル基本情報に記載あり。
・リダイレクトURL→AWS APIGatewayページより、デプロイしたAPIのステージ詳細に記載あり。

このリダイレクトURLはLINEDevelopersページ上で設定したコールバックURLと同じURLとなります。合わせて設定します。

今回リダイレクトを実施するため、レスポンスのstatuscodeは"302"、headersはリダイレクトURLを付与します。

参考ソースコード↓

lambda1.py
import json
import os

def lambda_handler(event, context):

    # ステート生成
    state = hashlib.sha256(os.urandom(32)).hexdigest()

    # 環境値(ご自身の環境値に置き換えてください。)
    redirect_uri = 'REDIRECT_URL'
    client_id = 'LINE_CHANNEL_ID'

    base_url = "https://access.line.me/oauth2/v2.1/authorize"
    params = {
        "response_type": "code",
        "client_id": client_id,
        "redirect_uri": redirect_uri,
        "state": state,
        "scope": "profile"
    }

    full_url = f"{base_url}?{'&'.join([f'{key}={value}' for key, value in params.items()])}"

    response = {
        'statusCode': 302,
        'headers': {
            'Location': full_url
        }
    }

    return response

2つ目のLambda関数

2つ目のLambda関数では、LINE認可したユーザー情報を取得し、完了した旨を返します。

完了すると、パラメータ"code"、"state"含みリダイレクトされます。
"code"パラメータをもとに、アクセストークンを取得します。
scope=profileの場合、このアクセストークンからLINEユーザーIDやLINE表示名を取得することも可能です(今回は対象外)

もしユーザーが認可しなかった場合、パラメーター"error"、"error_description"となります。されなかった場合の処理を別途考慮する必要があります。今回の実装ではエラーとして処理しています。

参考ソースコード

lambda2.rb
import json
import os
import urllib

def lambda_handler(event, context):

    #リクエスト情報取得
    parameters = event.get('queryStringParameters')

    #LINEエラーの場合は処理を終了する
    if 'error' in parameters:
        return {
            'statusCode': parameters['error'],
            'body': json.dumps({'message': parameters['error_description']}, ensure_ascii=False)
        }
    
    #リクエスト情報取得
    code = parameters['code']
    state = parameters['state']

    # 環境値(ご自身の環境値に置き換えてください。)
    redirect_uri = 'REDIRECT_URL'
    client_id = 'LINE_CHANNEL_ID'
    client_secret = 'LINE_CHANNEL_SEACRET'

    # LINE Messaging APIのエンドポイント
    line_api_endpoint_token = 'https://api.line.me/oauth2/v2.1/token'

    # LINEへアクセストークン取得リクエスト送信
    # リクエストヘッダー
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    # LINE APIの認証情報
    data = urllib.parse.urlencode({
        'grant_type': 'authorization_code',  
        'code': code,  
        'redirect_uri': redirect_uri,
        'client_id': client_id,  
        'client_secret': client_secret
    }).encode('utf-8')

    try:
        # HTTP POSTリクエストの送信
        request = urllib.request.Request(line_api_endpoint_token, data=data, headers=headers, method='POST')
        with urllib.request.urlopen(request, data=data) as f:
            response = f.read()
        line_info = json.loads(response)
        access_token = line_info['access_token']
        return {
            'statusCode': 200,
            'body': {
                'message': access_token
            }
        }

    except Exception as e:
        # エラーハンドリング
        error_message = e.read().decode("utf-8")
        return {
            'statusCode': e.code,
            'body': {
                'message': error_message
            }
        }

    return response

まとめ

今回は公式LINEアカウントのログイン認証行い、認可したユーザーのLINEユーザー情報を取得することができました。今回Lambda関数ではログイン処理しか行っていませんが、実際の実装では取得したユーザー情報をDB保存したりと他の処理を組み合わせて実装することが可能です。ウェブアプリにLINEログインをAWSで実装する際の参考になればと思います。

自身にとってAWSとLINE機能、両方において技術の理解を深めることができました。また後日、本開発環境のCI/CDに関する記事を投稿予定です。そちらもぜひ→PERSOL PROCESS & TECHNOLOGY Advent Calendar 2023

参考文献

ウェブアプリにLINEログインを組み込む

4
0
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
4
0