Nswag: JWT token injection in Typescript clients

Created on 9 Mar 2018  路  8Comments  路  Source: RicoSuter/NSwag

Hi Rico,

Could you please help.

How to generate Typescript client with JWT authorization token, injected into the header ?

Currently I have to inject token manually. Like:

setToken(headers) {
    const token = this.oidcSecurityService.getToken();
    if (token !== '') {
      const tokenValue = 'Bearer ' + token;
      headers.append('Authorization', tokenValue);
    }
    return headers;
  }

Then I've update all generated clients adding this line options_.headers = this.authTokenService.setToken(options_.headers); after options definition, like:

.........
    getAccounts(page: string | null, pageCount: string | null, contactIdList: string[] | null, sortingProperty: string | null, isDescending: boolean | null, version: string): Observable<ApplicationUser[]> {
        let url_ = this.baseUrl + "/api/{version}/accounts";
        if (version === undefined || version === null)
            throw new Error("The parameter 'version' must be defined.");
        url_ = url_.replace("{version}", encodeURIComponent("" + version));
        url_ = url_.replace(/[?&]$/, "");

        let options_ = {
            method: "get",
            headers: new Headers({
                "page": page !== undefined && page !== null ? "" + page : "",
                "pageCount": pageCount !== undefined && pageCount !== null ? "" + pageCount : "",
                "contactIdList": contactIdList !== undefined && contactIdList !== null ? "" + contactIdList : "",
                "sortingProperty": sortingProperty !== undefined && sortingProperty !== null ? "" + sortingProperty : "",
                "isDescending": isDescending !== undefined && isDescending !== null ? "" + isDescending : "",
                "Content-Type": "application/json",
                "Accept": "application/json"
            })
        };

        options_.headers = this.authTokenService.setToken(options_.headers);

        return this.http.request(url_, options_).flatMap((response_) => {
            return this.processGetAccounts(response_);
        }).catch((response_: any) => {
            if (response_ instanceof Response) {
                try {
                    return this.processGetAccounts(response_);
                } catch (e) {
                    return <Observable<ApplicationUser[]>><any>Observable.throw(e);
                }
            } else
                return <Observable<ApplicationUser[]>><any>Observable.throw(response_);
        });
    }
.......
done question

Most helpful comment

In addition to my question :) Found alternative solution to add TokenInterceptor .

Steps:

  1. Client should be generated with HttpClient option (@angular/common/http)
  2. Interceptor code:
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';

import { OidcSecurityService } from 'angular-auth-oidc-client';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class TokenInterceptor {

/**
 * Creates an instance of TokenInterceptor.
 * @param {OidcSecurityService} auth
 * @memberof TokenInterceptor
 */
constructor(public auth: OidcSecurityService) {}

/**
 * Intercept all HTTP request to add JWT token to Headers
 * @param {HttpRequest<any>} request
 * @param {HttpHandler} next
 * @returns {Observable<HttpEvent<any>>}
 * @memberof TokenInterceptor
 */
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
       setHeaders: {
           Authorization: `Bearer ${this.auth.getToken()}`
       }
    });

    return next.handle(request);
  }
}

  1. Update providers sections in app.module like:
 providers: [
    HttpClientModule,
    { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }
  ],

All 8 comments

You can define a base class and enable the useTransformOptionsMethod setting, as shown for example here:

https://github.com/Picturepark/Picturepark.SDK.TypeScript/blob/master/src/picturepark-sdk-v1-angular/nswag.json#L34

Thanks a lot. ;)

In addition to my question :) Found alternative solution to add TokenInterceptor .

Steps:

  1. Client should be generated with HttpClient option (@angular/common/http)
  2. Interceptor code:
import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';

import { OidcSecurityService } from 'angular-auth-oidc-client';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class TokenInterceptor {

/**
 * Creates an instance of TokenInterceptor.
 * @param {OidcSecurityService} auth
 * @memberof TokenInterceptor
 */
constructor(public auth: OidcSecurityService) {}

/**
 * Intercept all HTTP request to add JWT token to Headers
 * @param {HttpRequest<any>} request
 * @param {HttpHandler} next
 * @returns {Observable<HttpEvent<any>>}
 * @memberof TokenInterceptor
 */
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
       setHeaders: {
           Authorization: `Bearer ${this.auth.getToken()}`
       }
    });

    return next.handle(request);
  }
}

  1. Update providers sections in app.module like:
 providers: [
    HttpClientModule,
    { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }
  ],

I think it would be a good idea to add this to the wiki somewhere...

Good point.
Maybe if you could create empty Wiki page I would add description there.
What do you think ?

I moved the docs to a new page: https://github.com/RSuter/NSwag/wiki/SwaggerToTypeScriptClientGenerator%3A-Angular

It would be awesome if you could improve this page...

@RSuter Updated the wiki page. Please do not hesitate to review/correct it ;)

Hey @Boriszn, looks good. Thank you very much.

Was this page helpful?
0 / 5 - 0 ratings