ASP.NET MVCではおなじみのIdentityライブラリですね。ユーザー管理はこれに任せると開発が非常に楽になります。
ただ、いろいろとおせっかいもあるので今回は認証エラー時のお話をします。
401を返すと302が返ってくる
おっとまず日本語がおかしいぜ。
じゃなくてありのまま言いうとこうなります。
例えば単純にDBから全件取得だけのAPIで、認証されていないユーザーなら401を返すAPIを書いてみます。
[Route("api/projects")]
public class ProjectsController : Controller
{
private readonly DatabaseContext db;
public ProjectsController(DatabaseContext db)
{
this.db = db;
}
[Authorize]
[HttpGet]
public async Task<IEnumerable<Project>> GetProjects()
{
return await db.Projects.ToListAsync();
}
}
これで認証されていないクライアントからは401になると思うじゃん?でも実際は302(Found)が返ってくるんですよ。
ほらぁ(死亡)
Identityさんどうしてこんなことするん?
これはIdentityの仕様で、つまり認証されていない人はログインページまで飛びましょうね~ということをやってくれているのです。HeaderについているURLはデフォルトのもので、大体のシステムはこのURL飛べばログイン画面いけるっしょってこと。
MVCをがっつり使ってる人はそれでいいかもしれませんが、WebAPIとして使いたい人にとっては迷惑千万です。
401にするためのおまじない
Identityの認証にCookieを使っている場合にこういった挙動になるようです。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseIdentity();
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AutomaticChallenge = false
});
}
AutomaticChallenge
をfalseにすることによってリダイレクトがなくなります。
swaggerでアクセスすると401が返ってきます。
テストコードで動かすとInvalidOperationException
例外が発生します。
普通にステータスコード401のレスポンスでいいのに・・・。