見出し画像

Fetch APIからbearer tokenで認証する時の正しい渡し方に迷う

Fetch APIでのbearer tokenの渡し方について

▼ こういう場面で必要になる

  • 認証が必要なRest APIを呼び出す場合

  • Rest APIにJWTを渡したい場合

  • あるいは自分でRest APIを作ってる場合

僕の場合は最後のケースに当てはまります。
Node.js + ExpressでRest API的なのを作ってた時です。

▼ こういうRest APIを作った

  • JSONを返すGETメソッド

  • JWTによるユーザー認証が必要

※ JWT = JSON Web Token

それでFetch APIから自作のRest APIを呼び出しました

これが動いてくれなくて困ります。
何度やっても401エラーが返ってくるみたいな感じ

試行錯誤の上で分かったことを書き留めます。

最初にこういうqiitaの記事を見つけた

ググって解決策を探しました。

▼ こういうqiitaの記事を見つけた

オプションのheadersフィールドにHeadersオブジェクトもしくはJSONでHTTPリクエストヘッダの内容を指定することができます。

https://qiita.com/tomoyukilabs/items/9b464c53450acc0b9574
fetch('https://www.googleapis.com/userinfo/v2/me', {
  headers: { 'Authorization': 'Bearer: (アクセストークン)' }
}).then(function(response) {
  return response.json();
}).then(function(json) {
  ...
});

ヘッダーに Authorization を指定すればいいみたいです。


▼ こういうコードを書いてみたが…

const TOKEN = '【任意のJSON Web Token】';

fetch('/api/test'
      {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer: '+TOKEN,
          'Content-Type': 'application/json',
        }
      }
    ).then(async (response)=>{
      console.log('response : ', response);
      console.log('json : ', await response.json());
    }).then((data)=>{
      console.log('data : ', data);
    }).catch((error) => {
      console.error('error : ', error);
    });

▼ 返ってきたレスポンスの一部

ok :  false
redirected : false
status : 401
statusText : "Unauthorized"
type : "basic"

トークン自体に誤りはないのに "Unauthorized" が出てしまう

さらに別の記事書いてある方法も試したが…

さらにググって別の記事を見つけました。

▼ Sending Requests Using JavaScript Fetch API

You can pass HTTP headers to the fetch() request as the second parameter. For example, to pass the Bearer Token Authorization Header, call fetch() with the {headers: {Authentication: 'Bearer Token'}} parameter.

Fetch API Request with Bearer Token Authorization Header
fetch('https://reqbin.com/echo/get/json', {
headers: {Authentication: 'Bearer Token'}
})
.then(resp => resp.json())
.then(json => console.log(json))

https://reqbin.com/code/javascript/ricgaie0/javascript-fetch-api-example

Qiitaの記事だと 'Authorization' というフィールド名だったけど、
こっちの記事だと 'Authentication' という名前になってます。

どっちが正しいのか分からず困惑

あと Bearer のあとのコロン(:)はいらないみたいです。


そこでこの記事を参考にコードを書きなおしました。

▼ このようなコードを書いたが…

const TOKEN = '【任意のJSON Web Token】';

fetch('/api/test'
      {
        method: 'GET',
        headers: {
          'Authentication': 'Bearer '+TOKEN,
          'Content-Type': 'application/json',
        }
      }
    ).then(async (response)=>{
      console.log('response : ', response);
      console.log('json : ', await response.json());
    }).then((data)=>{
      console.log('data : ', data);
    }).catch((error) => {
      console.error('error : ', error);
    });

▼ 返ってきたレスポンスの一部

ok :  false
redirected : false
status : 401
statusText : "Unauthorized"
type : "basic"

やっぱり401エラーでユーザー認証がうまくいきません。

それぞれの記事は部分的に間違いがあるみたいです。

結局 'Authorization': 'Bearer …' が正解だった

ということで最終的に答えを見つけました。

  • Authorizationフィールドを使う

  • 'Bearer ' の後にトークンを渡す

Fetch APIだけではなくCurlによるリクエストでも同じです。


次のようなコードを試したら期待通りになりました。

▼ このコードでユーザー認証成功

const TOKEN = '【任意のJSON Web Token】';

fetch('/api/test'
      {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer '+TOKEN,
          'Content-Type': 'application/json',
        }
      }
    ).then(async (response)=>{
      console.log('response : ', response);
      console.log('json : ', await response.json());
    }).then((data)=>{
      console.log('data : ', data);
    }).catch((error) => {
      console.error('error : ', error);
    });

この仕様はNode.js + Expressだけに限らず、
Laravelとかで認証付きRest APIを作った場合も同じはずです。

これだけのことなのに、分からないと少し困惑します。

ググった情報も疑うことが大事(教訓)


この記事が気に入ったらサポートをしてみませんか?