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

注:ここでは、OpenID Connectプロトコルをサポートし、ユーザー情報をIDトークンで取得できるLINEログインv2.1をウェブアプリに組み込む方法について説明します。ウェブアプリにLINEログインv2を組み込む場合は、「ウェブアプリにLINEログインを組み込む(LINEログインv2)」を参照してください。

このページでは、ウェブアプリにLINEログインを組み込む方法について説明します。LINEログインを組み込めるアプリがない場合は、サンプルアプリを利用できます。「ウェブアプリでLINEログインを試してみる」を参照してください。

ログインのフロー

ウェブアプリ向けのLINEログインの処理(ウェブログイン)は、OAuth 2.0の認可コード付与のフローおよびOpenID Connectプロトコルに基づいています。アプリでLINEログインを利用するには、アプリからサーバーへのリクエスト送信と、LINEプラットフォームからアプリへのデータ受信を実行できる必要があります。ウェブログインのフローの概要は以下のとおりです。

LINEログインの認可フロー

ウェブログインの処理に伴うステップは、以下のとおりです。

  1. 必要なクエリパラメータを使用して、アプリからLINEログインの認可URLにユーザーを誘導します。
  2. LINEのログインダイアログがブラウザで開き、ユーザーはログインして認証を受けます。LINEプラットフォームでユーザーの資格情報が検証された後、ユーザーはアプリから要求される権限を付与することに同意する必要もあります。
  3. LINEプラットフォームからアプリに、redirect_uriを介してユーザーをリダイレクトします。このとき、認可コードとstateを含むクエリ文字列もアプリに送信されます。
  4. アプリは、認可コードを使ってエンドポイントURL https://api.line.me/oauth2/v2.1/tokenにアクセストークンを要求します。
  5. LINEプラットフォームがアプリからのリクエストを検証し、アクセストークンをアプリに返します。

取得したアクセストークンを使って、Social APIを呼び出すことができます。

始める前に

LINEログインをアプリに組み込む作業を始める前に、以下の作業が完了していることを確認します。

チャネルを設定する

リダイレクト先を設定する

ユーザーがログインした後のリダイレクト先を指定するには、コンソールの[アプリ設定]ページでコールバックURLを設定します。

注:複数のコールバックURLを指定できます。

リダイレクト設定

メールアドレス取得権限を申請する

LINEログインを使ってログインするユーザーに、メールアドレスの取得を要求できます。この機能を有効にするには、あらかじめコンソールから申請する必要があります。

  1. [Channel基本設定]ページの[OpenID Connect]セクションで、[メールアドレス]の隣の[申請]をクリックします。

    メールアドレス取得権限の申請

  2. 申請条件に同意して、メールアドレスの取得および利用についてユーザーに提示する文面のスクリーンショットをアップロードします。

申請が受理されると[メールアドレス]の下に「申請済み」と表示されます。

認可を要求する

ユーザーを認証してアプリに権限を付与するよう要求するには、以下の認可URLに必須のクエリパラメータを付けてユーザーをリダイレクトします。ユーザーをリダイレクトするには、LINEログインボタンか直接リンクを使います。

https://access.line.me/oauth2/v2.1/authorize

必須のクエリパラメータをURLに含める必要があります。

パラメータ タイプ 必須 説明
response_type String 必須 code。この値を指定することにより、LINEプラットフォームから認可コードが返されます。
client_id String 必須 チャネルID。LINEが発行した、チャネル固有の識別子。
redirect_uri String 必須 コールバックURL。認証と認可の後にユーザーがリダイレクトされるURLです。コンソールでチャネル向けに登録したコールバックURLと一致する必要があります。
state String 必須 クロスサイトリクエストフォージェリ防止用の固有な英数字の文字列。アプリ側でランダムに生成する必要があります。URLエンコードされた文字列は使用できません。
scope String 必須 ユーザーが付与する権限。URLエンコードされた空白文字(%20)で区切って、複数のスコープを指定できます。詳しくは、「スコープ」を参照してください。
nonce String 任意 リプレイアタックを防止するための文字列。この値はレスポンスで返されるIDトークンに含まれます。
prompt String 任意 consent。ユーザーが要求された権限をすべて付与済みであっても、強制的に同意画面を表示します。
bot_prompt String 任意 ボットを友だち追加するオプションをユーザーのログイン時に表示します。normalまたはaggressiveを指定します。詳しくは、「ボットをLINEログインのチャネルにリンクする」を参照してください。

スコープ

scopeパラメータに指定できるスコープは以下のとおりです。URLエンコードされた空白文字(%20)で区切って、複数のスコープを指定できます。少なくとも1つのスコープを指定する必要があります。

  • profile:ユーザーのプロフィール情報を取得する権限です。
  • openid:IDトークンを取得する権限です。詳しくは、「IDトークン」を参照してください。
  • email:ユーザーのメールアドレスを取得する権限です。openidを同時に指定する必要があります。詳しくは、「IDトークン」を参照してください。

ボットとユーザーの友だち関係を取得するにはprofileのスコープを持つアクセストークンが必要です。

認可リクエストの例

以下はクエリパラメータを含む認可URLの例です。

https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id=1234567890&redirect_uri=https%3A%2F%2Fexample.com%2Fauth&state=12345abcde&scope=openid%20profile&nonce=09876xyz

認証と認可のプロセス

ユーザーが認可URLにリダイレクトされると、LINEプラットフォームにより自動的にユーザーセッションが確認され、ユーザーのログイン状態が判別されます。ユーザーがLINEにログインしていない場合は、ユーザーは認証のためLINEログインダイアログにリダイレクトされます。ユーザーはメールアドレスとパスワードを使ってLINEにログインする必要があります。ユーザーセッションが存在し、LINEにログイン済みである場合は、LINEログインダイアログの代わりに確認画面が表示されます。

ユーザーがログインすると、同意画面が表示され、scopeパラメータで指定した権限の付与を求められます。

scopeパラメータで指定した権限がprofileまたはopenidの場合は、ユーザーが既に権限を付与していると同意画面は表示されません。権限にemailが含まれる場合は、promptパラメータの指定の有無にかかわらず、ログインするたびに同意画面が表示されます。

同意画面

認可コードを取得する

ユーザーの認証と認可が完了すると、HTTPステータスコード302および以下のクエリパラメータを含むコールバックURLが返されます。

パラメータ タイプ 説明
code String アクセストークンの取得に使用される認可コード。有効期間は10分です。また、認可コードは1回のみ利用可能です。
state String 元のリクエストの認可URLに含まれるstateパラメータ。この値が元のリクエストに含まれる値と一致することを、アプリが検証する必要があります。
friendship_status_changed Boolean チャネルにリンクされているボットとユーザーの関係が、ログイン時に変わった場合はtrueです。そうでなければfalseです。 認可の要求時にbot_promptクエリパラメータを指定し、かつ、ボットを友だち追加するオプションを含む同意画面がユーザーに表示された場合にのみ返されます。詳しくは、「ボットをLINEログインのチャネルにリンクする」を参照してください。

以下は、レスポンスの例です。

HTTTP/1.1 302 Found
Location : https://client.example.org/cb?code=abcd1234&state=0987poi&friendship_status_changed=true

エラーレスポンス

アプリの要求する権限の付与をユーザーが拒否した場合、以下のクエリパラメータを含むコールバックURLが返されます。

パラメータ タイプ 必須 説明
error String 必須 エラーコード
error_description String 任意 エラー内容。人間が判読できるASCIIエンコードのテキストです。 注:このパラメータは、iOSおよびAndroidアプリのアプリ内ブラウザでは表示されません。この問題については、現在対応中です。
state String 任意 OAuth 2.0のステート値。認可リクエストにstateパラメータが含まれていた場合は必ず返されます。

以下は、エラーレスポンスの例です。

https://example.com/callback?error=access_denied&error_description=The+resource+owner+denied+the+request.&state=0987poi

アプリの要求する権限の付与をユーザーが拒否した場合、アプリ側でエラーを適切に処理する必要があります。

アクセストークンを取得する

アクセストークンを取得するには、認可コードを指定してHTTP POSTリクエストを実行します。取得したアクセストークンで、APIを呼び出すことができます。アクセストークンは、以下のエンドポイントで発行されます。

リクエスト

POST https://api.line.me/oauth2/v2.1/token

リクエストヘッダー 説明
Content-Type application/x-www-form-urlencoded

リクエストボディ

リクエストボディの情報はform-urlencodedフォーマットで記述します。

パラメータ タイプ 必須 説明
grant_type String 必須 authorization_code。付与タイプを指定します。
code String 必須 認可コード
redirect_uri String 必須 コールバックURL
client_id String 必須 チャネルID。コンソールで確認できます。
client_secret String 必須 チャネルシークレット。コンソールで確認できます。

リクエストの例

以下はアクセストークンを取得するためのHTTP POSTリクエストの例です。

curl -X POST https://api.line.me/oauth2/v2.1/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d 'code=xxx' \
-d 'redirect_uri=xxx' \
-d 'client_id=xxx' \
-d 'client_secret=xxx'

レスポンス

LINEプラットフォームがアプリからのリクエストを検証し、以下の表に示すアクセストークンなどのデータをアプリに返します。

プロパティ タイプ 説明
access_token String アクセストークン。有効期間は30日です。
expires_in Number アクセストークンの有効期限が切れるまでの秒数。
id_token String ユーザー情報を含むJSONウェブトークン(JWT)。このプロパティは、スコープにopenidを指定した場合にのみ返されます。詳しくは、「IDトークン」を参照してください。
refresh_token String 新しいアクセストークンを取得するためのトークン。アクセストークンの有効期限が切れてから最長10日間有効です。
scope String ユーザーが付与する権限。ただし、emailスコープは権限が付与されていてもscopeプロパティの値としては返されません。
token_type String Bearer

以下は、JSONレスポンスの例です。

{
    "access_token": "bNl4YEFPI/hjFWhTqexp4MuEw5YPs...",
    "expires_in": 2592000,
    "id_token": "eyJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "Aa1FdeggRhTnPNNpxr8p",
    "scope": "profile",
    "token_type": "Bearer"
}

IDトークン

IDトークンは、ユーザー情報を含むJSONウェブトークン(JWT)です。IDトークンは、ピリオド(.)で区切られたヘッダー、ペイロード、および署名から構成されます。各部分はbase64urlでエンコードされています。詳しくは、JWTの仕様を参照してください。

ヘッダー

以下はデコードしたヘッダー値の例です。この例では、エンコードされたオブジェクトでHMAC SHA-256アルゴリズムが使用されていることを、ヘッダー部分で宣言しています。LINEログインではHMAC SHA-256のみを使用します。

{
  "alg": "HS256"
}
ペイロード

ユーザー情報はペイロード部分に含まれます。

フィールド 説明
iss https://access.line.me。IDトークンの生成URLです。
sub IDトークンの対象ユーザーID
aud チャネルID
exp トークンの有効期限。UNIXタイムです。
iat IDトークンの生成時間。UNIXタイムです。
nonce 認可URLに指定したnonceの値。認可リクエストにnonceの値を指定しなかった場合は含まれません。
name ユーザーの表示名。認可リクエストにprofileスコープを指定しなかった場合は含まれません。
picture ユーザープロフィールの画像URL。認可リクエストにprofileスコープを指定しなかった場合は含まれません。
email ユーザーのメールアドレス。認可リクエストにemailスコープを指定しなかった場合は含まれません。

以下はデコードしたペイロード部分の例です。

{
    "iss": "https://access.line.me", 
    "sub": "U1234567890abcdef1234567890abcdef ",
    "aud": "1234567890", 
    "exp": 1504169092, 
    "iat": 1504263657, 
    "nonce": "0987654asdf", 
    "name": "Taro Line", 
    "picture": "https://sample_line.me/aBcdefg123456", 
}
署名

署名を使ってレスポンスの有効性を検証します。Base64urlでエンコードされているヘッダー、ピリオド、およびペイロードを繋げた文字列を値とし、チャネルシークレットを鍵として、HMAC SHA-256アルゴリズムでハッシュ化した値をbase64urlでエンコードしたのが署名です。アプリのセキュリティを保つため、トークンの署名は必ず検証する必要があります。

IDトークンをデコードして検証する

IDトークンをデコードして検証するには、任意のJWTライブラリを使うか、 以下の手順に従います

JWTライブラリを使う

一般利用が可能なJWTライブラリを使って、IDトークンをデコードして検証できます。以下はPython向けライブラリを使ってIDトークンをデコードする例です。

import jwt

decoded_id_token = jwt.decode(id_token,
                              channel_secret,
                              audience=channel_id,
                              issuer='https://access.line.me',
                              algorithms=['HS256'])

# check nonce (Optional. But strongly recommended)
nonce = '_stored_in_session_'
expected_nonce = decoded_id_token.get('nonce')
if nonce != decoded_id_token.get('nonce'):
    raise RuntimeError('invalid nonce')

IDトークンをデコードして検証する

  1. ピリオド(.)を区切り文字として、ヘッダー、ペイロード、および署名を分割します。
  2. 各部分をbase64urlでデコードします。
  3. Base64urlでエンコードされたヘッダー、ピリオド、およびペイロードを繋げた文字列を値とし、チャネルシークレットを鍵として、ハッシュ値を算出します。この値がデコードした署名と同じであるかどうかを検証します。
  4. issの値がhttps://access.line.meであり、IDトークンがLINEから送信されたものであることを確認します。
  5. audの値がお使いのチャネルIDと一致しており、IDトークンがお使いのチャネルを対象としていることを確認します。
  6. IDトークンの有効性を確認するには、expの値が検証時より後のUNIXタイムスタンプであることを確認します。
  7. リプレイアタックを防止するため、nonceの値が認可リクエストに指定したnonceの値と等しいことを確認します。nonceの値をユーザーセッションと共に保存します。このステップは省略できますが、nonceの値を含めることを強くお勧めします。

以下はPython 3を使った例です。

import base64
import hashlib
import hmac
import json
import time


def base64url_decode(target):
    rem = len(target) % 4
    if rem > 0:
        target += '=' * (4 - rem)

    return base64.urlsafe_b64decode(target)


def check_signature(key, target, signature):
    calc_signature = hmac.new(
        key.encode('utf-8'),
        target.encode('utf-8'),
        hashlib.sha256
    ).digest()

    return hmac.compare_digest(signature, calc_signature)


def decode_id_token(id_token, channel_id, channel_secret, nonce=None):
    # step 1
    header, payload, signature = id_token.split('.')

    # step 2
    header_decoded = base64url_decode(header)
    payload_decoded = base64url_decode(payload)
    signature_decoded = base64url_decode(signature)

    # step 3
    valid_signature = check_signature(channel_secret,
                                      header + '.' + payload,
                                      signature_decoded)
    if not valid_signature:
        raise RuntimeError('invalid signature')

    payload_json = json.loads(payload_decoded.decode('utf-8'))

    # step 4
    if payload_json.get('iss') != 'https://access.line.me':
        raise RuntimeError('invalid iss')

    # step 5
    if payload_json.get('aud') != channel_id:
        raise RuntimeError('invalid aud')

    # step 6
    if int(time.time()) > payload_json.get('exp'):
        raise RuntimeError('invalid exp')

    # step 7 (Optional. But strongly recommended)
    if nonce is not None:
        if payload_json.get('nonce') != nonce:
            raise RuntimeError('invalid nonce')

    return payload_json

次のステップ

取得したアクセストークンを使ってSocial APIを呼び出し、ユーザーのログアウト、アクセストークンの管理、およびユーザープロフィール情報の取得を実行できます。詳しくは、以下のページを参照してください。


ご意見やご要望がある場合

LINEプラットフォームのドキュメントやサービスについてご不明な点があるときは、まず「FAQ」ページやCommunityサイトをご覧ください。疑問が解決しない、またはドキュメントの内容やLINEプラットフォームの機能についてご要望があれば、以下のボタンをクリックするか、GitHubのLINE Platform feedbackリポジトリにイシューを作成してお知らせください。