エンジニア初心者のためのwebAPI認証方式を整理してみた

webAPI認証方式 プログラミング

この記事では、エンジニア初心者向けにwebAPIの認証方式について、解説していきたいと思います。

自社のアプリケーションからサードパーティーのリソースにAPI経由でアクセスする際は、基本的にリクエストヘッダーに認証情報を含める必要があります。

APIを使用したいのに、認証の仕方が分からないエンジニア初心者の方向けに代表的な認証方式について、仕組みやサンプルコードを解説します。

この記事を読んでほしい方
  • エンジニア初心者の方
  • webAPIの基礎知識がある方
  • Javascriptの非同期処理の知識がある方

webAPIの基礎知識

webAPIとは

WebAPIは、ウェブ上で異なるアプリケーション同士が情報をやり取りするための手段です。これは、異なるプログラムやサービスが互いに通信し、データを共有することが可能になります。具体的には、外部の開発者やプログラムが、特定のサービスやデータにアクセスできるようにするプログラミングのインターフェースです。

例えば、天気情報のサービスが提供しているWebAPIを利用すると、他のアプリケーションやウェブサイトがその天気情報を取得できるようになります。これによって、異なるアプリケーション同士が連携し、より豊富で柔軟な機能を提供することが可能となります。

WebAPIは、HTTPプロトコルを通じてデータを受け渡しすることが一般的で、JSONXMLなどのデータ形式を使用します。これにより、クロスプラットフォームでの統一的なデータのやり取りが可能となり、異なるプログラミング言語やプラットフォームでも利用できる汎用性があります。

webAPIの認証とは

WebAPIの認証は、APIを利用する際に正当なユーザーであることを確認し、セキュリティを確保するための手続きです。認証は、アクセストークンやキーなどの情報を用いて行われ、これにより悪意ある利用や不正なアクセスを防ぎます。提供されるサービスにより、認証方式が異なるので、利用サービスのAPIリファレンスを参照の元、構築してください。

webAPIの認証方式の代表的なものには、以下があります。

webAPI認証の種類
  • Basic認証:ユーザー名とパスワードを使用してAPIにアクセスする方式。ユーザー名とパスワードをBase64エンコードした文字列をリクエストヘッダーに含める。
  • token認証:ユーザーが事前に取得したトークンを使用してAPIにアクセスする方式。トークンは一定期間有効で、有効期限が切れた場合は再取得が必要。
  • APIキーによる認証:ユーザーごとに発行される一意のキーを使用してAPIにアクセスする方式。キーが正しい場合にのみリクエストが受け付けられる。
  • OAuthによる認証:利用者がアプリケーションに対して特定の権限を与え、その権限を用いてAPIにアクセスする方式。アクセストークンを使用してリクエストを認可する。

以下で書く認証方式について、詳しく解説します。JavascriptのfetchAPIのサンプルコードも記載しています。

Basic認証

Basic認証の仕組みとメリット

Basic認証は、HTTPプロトコルにおいて最もシンプルな認証方式の一つです。

クライアントがサーバーにAPIリクエストを実行する際に、ヘッダーのAuthorizationの値に、ユーザー名とパスワードをBase64でエンコードした文字列を設定します

サーバー側は、上記の文字列からユーザー名とパスワードが認証システムに登録された情報と一致するか検証します。正しい場合は、リクエストが許可されレスポンスが返却されます。

ただし、Basic認証は通信が平文でやり取りされ、Base64でエンコードした文字列も簡単にデコードできてしまうため、セキュリティ要件に応じて利用を検討する必要があります。

Basic認証のサンプルコード

const url = "https://api.example.com/data";
const username = "your_username";
const password = "your_password";

// ユーザー名とパスワードをBase64エンコード
const base64Credentials = btoa(`${username}:${password}`);

// ヘッダーにAuthorizationを追加
const headers = new Headers({
  Authorization: `Basic ${base64Credentials}`,
  "Content-Type": "application/json", // レスポンスがJSON形式であることを示す
});

// GETリクエストを送信
fetch(url, {
  method: "GET",
  headers: headers,
})
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error("Fetch error:", error));

btoa関数を使用してユーザー名とパスワードをBase64エンコードし、それをAuthorizationヘッダーに含めています。

// ユーザー名とパスワードをBase64エンコード
const base64Credentials = btoa(`${username}:${password}`);

token認証

token認証の仕組みとメリット

token認証は、認証情報としてトークンを使用する仕組みです。一般的には、ユーザーが認証された後に発行されたトークンを使用してアクセスを許可します。

トークンには認証情報を直接含まないためユーザー名やパスワードが漏洩しても直接の影響を受けません。セキュリティが向上します

token認証のサンプルコード

const url = "https://api.example.com/data";
const accessToken = "your_access_token";

// ヘッダーにAuthorizationを追加
const headers = new Headers({
  Authorization: `Bearer ${accessToken}`,
  "Content-Type": "application/json", // レスポンスがJSON形式であることを示す
});

// GETリクエストを送信
fetch(url, {
  method: "GET",
  headers: headers,
})
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error("Fetch error:", error));

ヘッダー情報に、Bearer アクセストークンを含めてAPIリクエストを投げます。token認証はOAuth2.0のフローの中でも使用される仕組みです。

// ヘッダーにAuthorizationを追加
const headers = new Headers({
  Authorization: `Bearer ${accessToken}`,
  "Content-Type": "application/json", // レスポンスがJSON形式であることを示す
});

APIキー認証

APIキー認証の仕組みとメリット

APIキー認証は、簡単な認証手段の一つで、APIにアクセスする際に特定のキー(APIキー)を使用して認証を行います。API利用者は単にキーをリクエストに含めるだけでアクセスできます

APIプロバイダーは、API利用者に対して一意のAPIキーを発行します。このキーは通常、ダッシュボードや管理コンソールから取得できます。APIキーはユーザーの個別の認証情報とは独立しており、APIのアクセス権を管理するための独自の仕組みとして扱われます。

各リクエストにはキーが含まれているため、APIプロバイダーは利用者ごとにリソース使用量をトラッキングしやすくなります。ただし、APIキー認証はセキュリティ上のリスクを伴います。キーが漏洩した場合、第三者が不正にAPIにアクセスする可能性があるため、HTTPSを使用して通信を暗号化するなどの対策が必要です。

APIキー認証のサンプルコード

const url = "https://api.example.com/data";
const apiKey = "your_api_key_here";

// ヘッダーにAPIキーを追加
const headers = new Headers({
  "X-API-Key": apiKey,
  "Content-Type": "application/json", // レスポンスがJSON形式であることを示す
});

// GETリクエストを送信
fetch(url, {
  method: "GET",
  headers: headers,
})
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error("Fetch error:", error));

このコードでは、APIキーを"X-API-Key"というヘッダーに含めています。your_api_key_hereの部分には実際のAPIキーを代入する必要があります

// ヘッダーにAPIキーを追加
const headers = new Headers({
  "X-API-Key": apiKey,
  "Content-Type": "application/json", // レスポンスがJSON形式であることを示す
});

OAuth認証

OAuth認証の基本的な仕組み

OAuthは、ユーザーが他のWebサービスやアプリケーションにアクセス権を付与するための仕組みを提供します。これにより、ユーザーは自分の資格情報(ユーザー名とパスワード)を直接共有せずに、外部サービスにアクセスできるようになります。

Oauth2.0の構成
  • リソースオーナー(Resource Owner): ユーザー。リソースへのアクセス権を持つ実体。
  • クライアント(Client): ユーザーがアクセスしようとしているリソースに対するアクセス権を得るために使用されるアプリケーションやサービス。
  • リソースサーバー(Resource Server): リソースへのアクセス権を保持し、保護するサーバー。
  • 認可サーバー(Authorization Server): リソースオーナーのアクセス権を認可し、トークンを発行するサーバー。
認証の流れ
  1. クライアントの登録: クライアントは、認可サーバーに登録されます。これにより、クライアントは認可サーバーから発行されるクライアントIDおよびクライアントシークレットを取得します。
  2. ユーザーの認証と同意: ユーザーは、クライアントがアクセスしようとしているリソースに対するアクセス権を認可サーバーに与えます。
  3. アクセストークンの発行: 認可サーバーは、ユーザーが認可した後、クライアントに対してアクセストークンを発行します。
  4. アクセストークンを使用したリソースのアクセス: クライアントは、アクセストークンを使用してリソースサーバーからリソースにアクセスします。

OAuth 2.0の主なフロー

1.認可コードグラント(Authorization Code Grant)フロー

このフローは、Webアプリケーションやサーバーサイドのアプリケーション向けに設計されています。ユーザーがクライアントアプリケーションに対してアクセス権を与えるため、認可コードを介して行われます。

①クライアントアプリケーションがリダイレクトURIクライアントIDスコープを指定して認可エンドポイントにリクエストを送信します。

②リソースオーナーに認可の意思を確認します

③リソースオーナーは認可サーバーにログインし、クライアントにアクセス権を与えるか拒否します。

const authorizationEndpoint = 'https://authorization-server.com/authorize';
const params = {
  response_type: 'code',
  client_id: 'CLIENT_ID',
  redirect_uri: 'REDIRECT_URI',
  scope: 'SCOPE',
  state: 'STATE',
};

const authorizationUrl = `${authorizationEndpoint}?${new URLSearchParams(params)}`;

// ブラウザでリダイレクト
window.location.href = authorizationUrl;

response_type=codeはAuthorization Code Grantを使用することを示します。

④認可が成功すると、認可コードがリダイレクトURIに返されます。

REDIRECT_URI?code=AUTHORIZATION_CODE&state=STATE

⑤クライアントアプリケーションは認可コードクライアントシークレットを使用してトークンエンドポイントにリクエストを送信します

const tokenEndpoint = 'https://authorization-server.com/token';
const tokenParams = {
  grant_type: 'authorization_code',
  code: 'AUTHORIZATION_CODE',
  redirect_uri: 'REDIRECT_URI',
  client_id: 'CLIENT_ID',
  client_secret: 'CLIENT_SECRET',
};

fetch(tokenEndpoint, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams(tokenParams),
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Token request error:', error));

⑥アクセストークンを取得します

{
  "access_token": "ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "REFRESH_TOKEN",
  "scope": "SCOPE"
}

アクセストークンを利用して、リソースサーバーへアクセスします

const resourceEndpoint = 'https://api.example.com/resource';
const accessToken = 'YOUR_ACCESS_TOKEN';

// POSTリクエストのデータ(例:JSON形式)
const postData = {
  key1: 'value1',
  key2: 'value2',
};

// ヘッダーにアクセストークンを追加
const headers = new Headers({
  Authorization: `Bearer ${accessToken}`,
  'Content-Type': 'application/json',
});

// POSTリクエストを送信
fetch(resourceEndpoint, {
  method: 'POST',
  headers: headers,
  body: JSON.stringify(postData),
})
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log('Response:', data))
  .catch(error => console.error('Fetch error:', error));

2.インプリシットグラント(Implicit Grant)フロー

このフローは、クライアントアプリケーションがサーバーサイドでのトークン取得が不要なシンプルな場合に使用されます(JavaScriptやモバイルアプリなど)。
Implicit Grantはセキュリティ上の脆弱性が指摘されており、Authorization Code Grantが推奨されています
アクセストークンが直接リダイレクトURIに含まれます。

①クライアントアプリケーションがリダイレクトURIクライアントIDスコープを指定して認可エンドポイントにリクエストを送信します。

②リソースオーナーに認可の意思を確認します

③リソースオーナーは認可サーバーにログインし、クライアントにアクセス権を与えるか拒否します。

const authorizationEndpoint = 'https://authorization-server.com/authorize';
const params = {
  response_type: 'token',
  client_id: 'CLIENT_ID',
  redirect_uri: 'REDIRECT_URI',
  scope: 'SCOPE',
  state: 'STATE',
};

const authorizationUrl = `${authorizationEndpoint}?${new URLSearchParams(params)}`;

// ブラウザでリダイレクト
window.location.href = authorizationUrl;

response_type=tokenはImplicit Grantを使用することを示します。

④認可が成功すると、アクセストークンが直接リダイレクトURIに返されます。

REDIRECT_URI#access_token=ACCESS_TOKEN&token_type=bearer&expires_in=3600&scope=SCOPE&state=STATE

⑤アクセストークンを利用して、リソースサーバーへアクセスします

3.クライアントクレデンシャルズ(Client Credentials)フロー

このフローは、クライアントアプリケーションがユーザーの代わりにリソースにアクセスする場合に使用されます。

①クライアントアプリケーションがクライアント資格情報(クライアントIDクライアントシークレットID)を使用してトークンエンドポイントにリクエストを送信します。

const tokenEndpoint = 'https://authorization-server.com/token';
const tokenParams = {
  grant_type: 'client_credentials',
  client_id: 'CLIENT_ID',
  client_secret: 'CLIENT_SECRET',
  scope: 'SCOPE',
};

fetch(tokenEndpoint, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams(tokenParams),
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Token request error:', error));

②認可サーバーはクライアント資格情報を検証し、アクセストークンを返します。

{
  "access_token": "ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "SCOPE"
}

アクセストークンを利用して、リソースサーバーへアクセスします

まとめ

初心者エンジニアがWebAPI認証を理解するためには、まず基本的な概念を掴むことが重要です。APIキー、Bearerトークン、Basic認証などの認証手法の違いや、セキュリティ意識を持ちHTTPSを使用するなどの基本的な実装手順を学ぶことがポイントです。例えば、APIキーは単純ながら有効で、BearerトークンはOAuthに基づく柔軟性があります。フローの理解と実際のサンプルコードで手を動かすことで、認証の基礎を築けます。

タイトルとURLをコピーしました