# Get profile information from ID tokens

The LINE Platform issues ID tokens compliant with the OpenID Connect (opens new window) specification, allowing you to securely obtain user profile information (user ID, display name, profile picture, email address) from the LINE Platform.

If you have LINE Profile+ permission, you can also safely obtain data registered with LINE Profile+ (name, gender, birthday, phone number, address). For more information, see Get user data registered with LINE Profile+.

# Get an ID token

You can also get an ID token when you get an access token.

You can also get an ID token with the LIFF app.

You can also use liff.getIDToken() to get an ID token.

# Get profile information from an ID token

Verify an ID token through one of these methods before using the information it contains:

# Use a LINE Login API endpoint

Simply by sending the ID token that you acquired with the access token and LINE Login channel ID to our dedicated API endpoint, you can verify the ID token and get the corresponding user's profile information and email address.

Example request:

curl -v -X POST 'https://api.line.me/oauth2/v2.1/verify' \
 -d 'id_token=eyJraWQiOiIxNmUwNGQ0ZTU2NzgzYTc5MmRjYjQ2ODRkOD...' \
 -d 'client_id=1234567890'

Example response:

{
    "iss": "https://access.line.me",
    "sub": "U1234567890abcdef1234567890abcdef",
    "aud": "1234567890",
    "exp": 1504169092,
    "iat": 1504263657,
    "nonce": "0987654asdf",
    "amr": [
        "pwd",
        "linesso",
        "lineqr"
    ],
    "name": "Taro Line",
    "picture": "https://sample_line.me/aBcdefg123456",
    "email": "taro.line@example.com"
}

For more information, see Verify ID token in the LINE Login API reference.

# Write code to validate ID tokens

You can use any JWT library (opens new window) or write your own code from scratch to validate ID tokens and obtain user profile information and email addresses.

# ID tokens

ID tokens are JSON web tokens (JWT) with information about the user. The ID token consists of a header, payload, and signature separated by period (.) characters. Each part is a base64url-encoded value. For more information, see the JWT (opens new window) specification.

These are the values included in the header.

Property Type Description
alg String ID token signature algorithm. For native apps, LINE SDK, or LIFF apps, ES256 (ECDSA using P-256 and SHA-256) is returned, and for web login, HS256 (HMAC using SHA-256) is returned.
type String Payload format. JWT is returned.
kid String Public key ID. Included in a header only when the value of alg is ES256. For more information on the kid property, see the JSON Web Key (JWK) document (opens new window). For getting public key, see Get public key using kid.

This is an example of a decoded header portion.

When alg is HS256:

{
  "typ": "JWT",
  "alg": "HS256"
}

When alg is ES256:

{
  "typ": "JWT",
  "alg": "ES256",
  "kid": "a2a459aec5b65fa..."
}
# Payload

The user's information is found in the payload section.

Property Type Description
iss String https://access.line.me. URL where the ID token is generated.
sub String User ID for which the ID token is generated
aud String Channel ID
exp Number The expiry date of the ID token in UNIX time.
iat Number Time when the ID token was generated in UNIX time.
auth_time Number Time when the user was authenticated in UNIX time. Not included if the max_age parameter wasn't specified in the authorization request.
nonce String The nonce value specified in the authorization URL. Not included if the nonce value was not specified in the authorization request.
amr Array of strings List of authentication methods used by the user. It includes one of the values below. For more information on each of these authentication methods, see User authentication.
  • pwd: Log in with email and password
  • lineautologin: LINE automatic login (including through LINE SDK)
  • lineqr: Log in with QR code
  • linesso: Log in with single sign-on
name String User's display name. Not included if the profile scope was not specified in the authorization request.
picture String User's profile image URL. Not included if the profile scope was not specified in the authorization request.
email String User's email address. Not included if the email scope was not specified in the authorization request.

This is an example of a decoded payload section.

{
    "iss": "https://access.line.me",
    "sub": "U1234567890abcdef1234567890abcdef ",
    "aud": "1234567890",
    "exp": 1504169092,
    "iat": 1504263657,
    "nonce": "0987654asdf",
    "amr": ["pwd"],
    "name": "Taro Line",
    "picture": "https://sample_line.me/aBcdefg123456"
}
# Signature

The signature is used to verify the validity of the response. The signature is a base64url-encoded hash computed using the HMAC SHA-256 algorithm with the base64url-encoded header + "." + payload as the value and the channel secret as a key. To ensure the security of your app, you should always verify the signature of the ID token.

# Get public key using kid

Follow these steps to get the public key using the kid property included in the header of the decoded ID token of native apps, LINE SDK and LIFF apps:

  1. Check the kid property of the Decoded ID token header.
  2. Access the LINE OpenID Connect Discovery document URL (opens new window) and receive a response object. For more information on properties included in the response object and their values, see OpenID Connect Discovery 1.0 (opens new window).
  3. The response object contains the jwks_uri property and its value https://api.line.me/oauth2/v2.1/certs. Access the JSON Web Key (JWK) document URL (opens new window) and receive the JSON array of JSON Web Key (JWK). For more information on JWK specifications, see JSON Web Key (JWK) (opens new window).
  4. In the JSON array, the element that contains the kid property identified in step 1 is the public key.

# Decode and validate ID tokens

To decode and validate ID tokens, you can either use a JWT library or follow the instructions below.

# Use a JWT library

You can use the publicly available JWT libraries (opens new window) to decode and verify your ID tokens. The following is an example of how to decode an ID token using a library for Python®.

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')
# Decode and validate ID token
  1. Split the header, payload, and signature sections using the period (.) character.
  2. Base64-URL decode each section
  3. Compute the hash using the base64url-encoded header + "." + payload as the value and the channel secret as a key. Verify that the value is the same as the decoded signature.
  4. Confirm that the ID token was sent from LINE by checking that the value of iss is https://access.line.me.
  5. Confirm that the ID token is for your channel by checking that aud matches your channel ID.
  6. To confirm the validity of the ID token, confirm that the exp value is greater than the UNIX timestamp at the time of verification.
  7. To prevent replay attacks, confirm that the value of nonce is the same as the nonce value specified in the authorization request. Store the nonce value with the user session. Although this step is optional, we strongly recommend including the nonce value.

The following is an example using 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