前提・実現したいこと
Angular (v7) + Express (v4) で Web アプリをローカルマシンで開発しています。
OAuth を利用した認証付きのサイトにするために、 CORS に対応したロジックにしようとしており、
認証に関わる API が呼ばれたら OAuth の認証ページにリダイレクトする機構にしようとしています。
ひとまずは、特定の API が呼ばれた時に、 一旦 OAtuh とは全く関係無い別のよく知られたサイト (今回は Yahoo Japan に飛ばそうとしてます。) にリダイレクトだけさせてみようとしているのですが、
どうしても Chrome のコンソールで以下のエラーが出力されて、リダイレクト先に遷移が行われません。
(尚、認証をしなければ、既存の内部の API 通信処理は問題なく意図した動作ができることを確認しており、あとは認証機構だけ入れれば完了という状態になっています。)
発生している問題・エラーメッセージ
動作確認 Web ブラウザは Chrome です。
ブラウザの開発者ツール「Console」の結果
ブラウザコンソールに以下のコンソールログが吐かれてます。
- Error ログ
Access to XMLHttpRequest at 'https://www.yahoo.co.jp/' (redirected from 'http://localhost:3000/api/auth') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- たて続けに出ている Warn ログ
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.yahoo.co.jp/ with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
ブラウザの開発者ツール「Network」の結果
- http://localhost:3000/api/auth の結果(後述の試したパターンの内の一例)
text
1【General】 2Request URL: http://localhost:3000/api/auth 3Request Method: GET 4Status Code: 302 Found 5Remote Address: [::1]:3000 6Referrer Policy: no-referrer-when-downgrade 7 8【Response Headers】 9Access-Control-Allow-Origin: * 10Connection: keep-alive 11Content-Length: 46 12Content-Type: text/plain; charset=utf-8 13Date: Thu, 14 Mar 2019 08:54:36 GMT 14Location: https://www.yahoo.co.jp/ 15Vary: Accept 16X-Powered-By: Express 17 18【Request Headers】 19Accept: application/json, text/plain, */* 20Accept-Encoding: gzip, deflate, br 21Accept-Language: ja,en-US;q=0.9,en;q=0.8 22Connection: keep-alive 23Content-Type: application/json 24Host: localhost:3000 25Referer: http://localhost:3000/ 26User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
text
1【General】 2Request URL: https://www.yahoo.co.jp/ 3Request Method: OPTIONS 4Status Code: 200 5Remote Address: 183.79.250.251:443 6Referrer Policy: no-referrer-when-downgrade 7 8【Request Headers】 9Provisional headers are shown 10Access-Control-Request-Headers: content-type 11Access-Control-Request-Method: GET 12Origin: http://localhost:3000 13Referer: http://localhost:3000/ 14User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
該当のソースコード
クライアント側
クライアントの API 呼び出しは以下のサービスクラスで実行。CORS の対応は、クライアント側は特に無い認識です。
ts
1import { Injectable } from '@angular/core'; 2import { HttpClient, HttpHeaders, HttpParams, HttpResponse, HttpErrorResponse } from '@angular/common/http'; 3 4@Injectable({ providedIn: 'root' }) 5export class HttpService { 6 7 constructor(protected http: HttpClient) { } 8 9 // API 呼出メソッド (GET) 10 private async get(): Promise<any> { 11 try { 12 const url = 'http://localhost:3000/api/auth'; 13 const httpParams: HttpParams = new HttpParams(); 14 15 // HTTP通信 実行 16 const response = await this.http.request<Res>(method, url, { 17 headers: new HttpHeaders({ 'Content-Type': 'application/json' }), 18 responseType: 'json', 19 params: httpParams 20 }).toPromise(); 21 22 return { ok: true, status: 200, body: response }; 23 } catch (error) { 24 return { ok: false, body: undefined }; 25 } 26 } 27}
サーバ側
こっちで CORS 対応を頑張れば良い認識。
以下の3種類のソースで試してみてますが、いずれも全く同じエラーでうまくいきません。
パターン1:ワイルドカードで全て CORS 許可
レスポンスヘッダは、ベタ書き
ts
1import * as express from 'express'; 2import * as bodyParser from 'body-parser'; 3import { join } from 'path'; 4 5const app = express(); 6 7// CORS 対応 (ベタ書き) 8app.use((req, res, next) => { 9 res.header('Access-Control-Allow-Origin', '*'); 10 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, application/json, Accept, x-client-key, x-client-token, x-client-secret, Authorization'); 11 res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 12 next(); 13}); 14 15// API ルーティング提供 (一応 ボディパーサも対応) 16app.use(bodyParser.urlencoded({ extended: true })); 17app.use(bodyParser.json({ limit: '100kb' })); 18app.get('/api/auth', (req, res) => { 19 res.redirect('https://www.yahoo.co.jp/'); 20}); 21 22// クライアント静的ファイル提供 23app.use(express.static(join(process.cwd(), 'dist/my-web-app'))); 24 25// アプリ起動 26app.listen(3000);
パターン2:Origin を2サイト明示して、 更にヘッダに "Credentials: True" を設定
こちらもレスポンスヘッダは、ベタ書き
ts
1import * as express from 'express'; 2import * as bodyParser from 'body-parser'; 3import { join } from 'path'; 4 5const app = express(); 6 7// CORS 対応 (ベタ書き) 8app.use((req, res, next) => { 9 res.header('Access-Control-Allow-Origin', 'http://localhost:3000, https://www.yahoo.co.jp/'); 10 res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, application/json, Accept, x-client-key, x-client-token, x-client-secret, Authorization'); 11 res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); 12 res.header('Access-Control-Allow-Credentials', 'true'); 13 next(); 14}); 15 16app.use(bodyParser.urlencoded({ extended: true })); 17app.use(bodyParser.json({ limit: '100kb' })); 18app.get('/api/auth', (req, res) => { 19 res.redirect('https://www.yahoo.co.jp/'); 20}); 21 22app.use(express.static(join(process.cwd(), 'dist/my-web-app'))); 23 24app.listen(3000);
パターン3:npm パッケージ「cors」を利用
ts:server.ts
1import * as cors from 'cors'; // 追加 2import * as express from 'express'; 3import * as bodyParser from 'body-parser'; 4import { join } from 'path'; 5 6const app = express(); 7 8// CORS 対応 (全て CORS 許可する設定で利用) 9app.use(cors()); 10 11app.use(bodyParser.urlencoded({ extended: true })); 12app.use(bodyParser.json({ limit: '100kb' })); 13 14app.get('/api/auth', (req, res) => { 15 res.redirect('https://www.yahoo.co.jp/'); 16}); 17 18app.use(express.static(join(process.cwd(), 'dist/my-web-app'))); 19 20app.listen(3000);
上記の3パターンを試しても、CORS 対応はできず、他のネット記事をみても同じような対応しか見当たらない状況です。
どなたか原因または解消方法がわかる方はいますでしょうか?
補足情報(FW/ツールのバージョンなど)

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。