卒研でWebアプリを開発しており、ログインセッションの実現をしようとしていたところ思いのほか躓いたので記事書くことにしました。
ここではExpressでのsession構築、Redis構築の話は一切行いません。予めご了承ください。
説明は致しませんが、この記事の最下部にて私が参考にしたURLを貼っております。
Cookieがセットされない…
express-sessionというライブラリを使って、Redisにセッション情報を保存しつつログインセッションを実現しようと思い環境構築を行っていました。
いろんな方のブログや公式リファレンスを参考にして、いざやってみるとなぜかブラウザにCookieがセットされない。
ブラウザの検証ツールで確認してみると、通信は正常に行われており、Set-Cookieもレスポンスヘッダーに存在し、ますます路頭に迷う羽目となっておりました。
ざっくり環境
-
Front: SvelteKit & Svelte
- Library: Axios
- Back: Node.js(Express)
- DBMS: Redis
- Middle: Docker・Docker Compose・Ubuntu(limaというアプリで仮装環境構築)
結論
import axios from 'axios';
const axiosInstance = axios.create({
baseURL: 'http://localhost:3000',
headers: {
'Content-Type': 'application/json',
'X-Request_With': 'XMLHttpRequest',
},
responseType: 'json',
withCredentials: true, // AjaxでCookieを使用するのに必須
});
フロント側では、Ajaxを行う際にAxiosを使用。
今までwithCredentials
というオプションはつけていなかったのですが、AjaxでCookieを使用する場合は必要みたいですので、付け加えます。
...が、フロント側でwithCredentials
をつけても、サーバー側で許可してない場合、CORS Policy違反となりフロントとサーバーのやりとりが拒絶されます。
なので、サーバー側でCORS Policyの設定を行います
// 上記の方で色々importやインスタンス化を行っているが結構あるため省略
app.set('trust proxy', 1);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
// express-sessionというライブラリでsessionを実現
// そのためのconfig
expressSession({
secret: 's3Cur3',
name: 'session',
resave: false,
saveUninitialized: true,
store,
})
);
// CORS系設定
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', ['http://localhost:5000']);
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, x-request_with, XMLHttpRequest')
// ↓がwithCredentialsを許可する設定
res.header('Access-Control-Allow-Credentials', 'true')
next();
});
上記では、withCredentials
について、「AjaxでCookieを使用する場合は必要」と記述したのですが、正確には以下のようです
Access-Control-Allow-Credentials レスポンスヘッダーは、リクエストの資格情報モード (Request.credentials) が include である場合に、レスポンスをフロントエンドの JavaScript コードに公開するかどうかをブラウザーに指示します。
証明書の資格情報モード (Request.credentials) が include である場合、レスポンスがフロントエンドの JavaScript コードに公開されるのは Access-Control-Allow-Credentials の値が true である場合のみです。
資格情報は Cookie、認証ヘッダー、または TLS クライアント証明書です。Access-Control-Allow-Credentials - HTTP - MDN Web Docs
AjaxはJavaScriptを用いて非同期的に通信を行うもので、その際にCookie、認証ヘッダー、TLSクライアント証明書を使用するにはwithCredentialsのCORSをtrueにする必要があるみたいです。
参考先