MeWrite Docs

Bearer Token Malformed

Authorization ヘッダーのBearerトークンの形式が不正な場合に発生するエラー

概要

Bearer Token Malformed は、HTTPリクエストのAuthorizationヘッダーに含まれるBearerトークンの形式が不正な場合に発生するエラーです。トークン文字列のフォーマット不正、コピー時の空白混入、JWT構造の不備などが原因です。

エラーメッセージ

JsonWebTokenError: jwt malformed
Error: Format is Authorization: Bearer [token]
{"error": "invalid_token", "error_description": "The access token is malformed"}
jwt.exceptions.DecodeError: Not enough segments
Error: Bearer token is not a valid JWT: wrong number of segments

原因

  1. Authorization ヘッダーのフォーマット不正: Bearer プレフィックスの欠落やスペルミス
  2. トークン文字列の破損: コピー時の空白、改行、不完全なコピー
  3. JWT構造の不備: ヘッダー.ペイロード.署名の3パートになっていない
  4. Base64エンコードの問題: パディング文字(=)の欠落やURLセーフエンコードの不一致
  5. トークンタイプの混同: リフレッシュトークンをアクセストークンとして使用

解決策

1. 正しいAuthorizationヘッダーの形式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 正しい形式
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U" \
  https://api.example.com/resource

# よくある間違い
# NG: Bearer が欠落
curl -H "Authorization: eyJhbGciOi..." https://api.example.com/resource

# NG: bearer(小文字)
curl -H "Authorization: bearer eyJhbGciOi..." https://api.example.com/resource

# NG: Bearer の後にスペースがない
curl -H "Authorization: BearereyJhbGciOi..." https://api.example.com/resource

# NG: 余分な空白や引用符
curl -H "Authorization: Bearer \"eyJhbGciOi...\"" https://api.example.com/resource

2. JWT の構造を確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// JWT は3つのパート(ドット区切り)で構成される
// header.payload.signature
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U';

const parts = token.split('.');
console.log('Parts count:', parts.length); // 3 であるべき
console.log('Header:', parts[0]);
console.log('Payload:', parts[1]);
console.log('Signature:', parts[2]);

// デコードして確認
const header = JSON.parse(Buffer.from(parts[0], 'base64url').toString());
const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());
console.log('Decoded header:', header);   // { alg: 'HS256', typ: 'JWT' }
console.log('Decoded payload:', payload); // { sub: '1234567890', ... }

3. サーバー側でのトークンパース

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Express.js ミドルウェア
function extractBearerToken(req, res, next) {
  const authHeader = req.headers.authorization;

  if (!authHeader) {
    return res.status(401).json({ error: 'Authorization header is missing' });
  }

  // "Bearer " プレフィックスの確認
  if (!authHeader.startsWith('Bearer ')) {
    return res.status(401).json({
      error: 'invalid_token',
      message: 'Format is: Authorization: Bearer [token]'
    });
  }

  const token = authHeader.slice(7).trim(); // "Bearer " を除去

  if (!token) {
    return res.status(401).json({ error: 'Token is empty' });
  }

  // JWT 形式の基本チェック
  const parts = token.split('.');
  if (parts.length !== 3) {
    return res.status(401).json({
      error: 'invalid_token',
      message: `JWT must have 3 parts, got ${parts.length}`
    });
  }

  req.token = token;
  next();
}

4. Python でのトークン検証

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import jwt

def verify_bearer_token(auth_header):
    if not auth_header:
        raise ValueError("Authorization header is missing")

    parts = auth_header.split()

    if len(parts) != 2 or parts[0].lower() != 'bearer':
        raise ValueError("Format is: Authorization: Bearer [token]")

    token = parts[1]

    try:
        decoded = jwt.decode(
            token,
            key=SECRET_KEY,
            algorithms=['HS256'],
            options={'verify_exp': True}
        )
        return decoded
    except jwt.InvalidTokenError as e:
        raise ValueError(f"Invalid token: {e}")

5. デバッグツール

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# JWT の中身をデコード(検証なし)
echo "eyJhbGciOiJIUzI1NiIs..." | cut -d'.' -f1 | base64 -d 2>/dev/null | jq .
echo "eyJhbGciOiJIUzI1NiIs..." | cut -d'.' -f2 | base64 -d 2>/dev/null | jq .

# トークンの文字数と形式を確認
TOKEN="eyJhbGciOiJIUzI1NiIs..."
echo "Length: ${#TOKEN}"
echo "Parts: $(echo $TOKEN | tr '.' '\n' | wc -l)"

# 不可視文字がないか確認
echo -n "$TOKEN" | cat -v

# jwt.io でオンライン検証(機密トークンは使用しないこと)
# https://jwt.io/

6. フロントエンドでのトークン送信

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// localStorage からトークンを取得して送信
const token = localStorage.getItem('access_token');

// トークンの基本検証
if (!token || token.split('.').length !== 3) {
  console.error('Invalid token format, redirecting to login');
  window.location.href = '/login';
}

const response = await fetch('/api/data', {
  headers: {
    'Authorization': `Bearer ${token}`, // テンプレートリテラルで正確に構築
    'Content-Type': 'application/json'
  }
});

関連エラー

Security の他のエラー

最終更新: 2026-02-03