2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

`openapi-generator`の`dart-dio-next`で生成したコードでAuthorizationヘッダーにBearerトークンを指定する

Posted at

書くこと

  • openapi-generatordart-dio-nextで生成したコードでAuthorizationヘッダーにBearerトークンを指定する方法
  • 自動生成されるBearerトークンを指定処理のソースコードの解説

書かないこと

  • APIのパスを定義した完全なOpenAPI定義について
  • openapi-generatorの実行環境について
  • OpenAPIについて

openapi-generatorについて

OpenAPI v3の 定義からソースコードを自動生成するツール。
今回使うgenerateテンプレートはdart-dio-nextというdio パッケージを使ったDartのソースコード

OAS定義

公式リファレンスに従いOASを定義していきます。

openapi.yml
security:
  - bearerAuth: []

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

openapi-generator実行

細かいパラメーターは各環境に合わせてください

$ openapi-generator generate -i openapi.yml -g dart-dio-next

API呼び出しとトークン設定

自動生成したパッケージのクラスに対してsetBearerAuthを呼び出し第一引数にOASのsecuritySchemesで指定したスキーマの名前'bearerAuth'を、第二引数にトークンの値を設定します。

final client = HttpClient();
client.setBearerAuth('bearerAuth', 'abc');

詳細

出力されるdart パッケージのlib/api.dartに以下のようにBearer tokenを設定する関数が定義されています。

lib/api.dart
  void setBearerAuth(String name, String token) {
    if (this.dio.interceptors.any((i) => i is BearerAuthInterceptor)) {
      (this.dio.interceptors.firstWhere((i) => i is BearerAuthInterceptor) as BearerAuthInterceptor).tokens[name] = token;
    }
  }

この関数ではBearerAuthInterceptortokensメンバに値を代入します。
setBearerAuth('bearerAuth', 'abc')としたので'bearerAuth' keyに'abc' valueを代入しています。
実際にリクエストを行う際BearerAuthInterceptoronRequestでインターセプト処理が行われます。
lib/auth/bearer_auth.dartは以下のように定義されています。

lib/auth/bearer_auth.dart
class BearerAuthInterceptor extends AuthInterceptor {
  final Map<String, String> tokens = {};

  @override
  void onRequest(
    RequestOptions options,
    RequestInterceptorHandler handler,
  ) {
    final authInfo = getAuthInfo(options, (secure) => secure['type'] == 'http' && secure['scheme'] == 'bearer');
    for (final info in authInfo) {
      final token = tokens[info['name']];
      if (token != null) {
        options.headers['Authorization'] = 'Bearer ${token}';
        break;
      }
    }
    super.onRequest(options, handler);
  }
}

getAuthInfo関数を呼び出してその結果をループし、tokensに格納されている前述したBearer tokenを 取り出してヘッダーに設定しています
getAuthInfoの 引数に定義されている以下の関数はOASで定義したsecuritySchemesを取得する関数です。

(secure) => secure['type'] == 'http' && secure['scheme'] == 'bearer'`

そのため、前述したOASでsecuritySchemesを定義していないとこのメソッドは意図した通りに動きません。

securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

getAuthInfo関数はlib/auth/auth.dartは以下のように定義されています。

auth.dart
abstract class AuthInterceptor extends Interceptor {
  /// Get auth information on given route for the given type.
  /// Can return an empty list if type is not present on auth data or
  /// if route doesn't need authentication.
  List<Map<String, String>> getAuthInfo(RequestOptions route, bool Function(Map<String, String> secure) handles) {
    if (route.extra.containsKey('secure')) {
      final auth = route.extra['secure'] as List<Map<String, String>>;
      return auth.where((secure) => handles(secure)).toList();
    }
    return [];
  }
}

OASのsecuritySchemesで指定した値をリストで取得します。bearerFormatを扱う機能は提供されていないようでリストから除外されています。

[{type: http, scheme: bearer, name: bearerAuth}]

環境

  • openapi-generator-cli v5.3.1
  • Dart SDK version: 2.16.0
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?