Blazor JWT 인증/권한 예제

Blazor Server JWT 인증/권한 예제입니다.

:package: 사용된 Packages

  • Blazored.LocalStorage (ver 4.4.0)
  • Microsoft.AspNetCore.Authentication.JwtBearer (ver 7.0.10)
  • System.IdentityModel.Tokens.Jwt (ver 6.32.2)

:open_book: 참고 가능한 Skills

  • 인증
    – JWT Token
    – Token 암호화
    – Token 검증
    – LocalStorage 활용
    – Claim 생성, 부여

  • 권한
    – Claims 확인
    – AuthorizeRouteView
    – 컴포넌트/페이지별 Authorize (by Roles)
    – 페이지 내부에서 Role에 따라 다른 output 구현


사실 소스코드를 하나하나씩 쪼개서 Slog에 설명과 덧붙여서 올리려 했는데, 시간이 허락하질 않아서… :sob:

최대한 참고가 되실만한게 있도록 정리는 해보았으나, 실력이 아직 미천합니다…

Blazor하시는 분들께 조금이라도 도움되셨으면 좋겠습니다. :blush:

9 Likes

코드를 보며 드는 의문이 있습니다.

  1. 인증 미들웨어 설정 불필요

인증 미들웨어를 한 번도 호출하지 않기 때문에 토큰을 설정할 필요는 없어 보입니다.

  1. IsAuthenticated 도 불필요.

AuthorizeView 가 GetAuthenticationState 를 자동으로 호출하기 때문에 두 개를 다 쓸 필요는 없습니다.

  1. 로컬 저장소

혹시, 로그인 한 후에 로그아웃하지 않고 창을 닫은 후, 다시 접속하면 로그아웃 상태인지 확인해 보셨나요? 제가 보기에는 로그인 상태가 유지될 것 같습니다.

5 Likes

1항목에 대해서는 미들웨어 사용선언을 하지않는다면 다른 기능들이 아예 작동을 하지않을텐데…
2번도 내일 테스트해보겠습니다~!
3번은 의도한게 맞습니다.
피드백 감사합니다!

2 Likes

Authentication 은 MainLayout 과 Login 에서 처리하고 있기 때문에, 현재 필요한 것은 AuthorizeView 가 요구하는 AuthorozationPolicy 입니다.
기본 정책 제공자를 설정하는 AddAuthorizationCore 확장 메서드가 있습니다.

4 Likes

예제 써주셔서 감사합니다!
진짜 만에하나 아쉬운 부분이 있다고 하신 게 맞다고 쳐도(에이 설마요),
이런거 하나하나가 귀중한 정보거든요.

2 Likes

1항목 확인 결과.
말씀하신게 맞네요…
builder.Services.AddAuthentication ~ AddJwtBearer 다 지우고

builder.Services.AddAuthenticationCore();
이 한줄만 넣어도 똑같이 작동이 되네요…ㄷㄷ
토큰을 사용하려면 반드시 AddJwtBearer가 선언되어야 하는줄 알았더니…


2항목 확인 결과.

이 부분도 확인되었어요. GetAuthenticationState가 자동으로 호출되는걸 이제 알게됐습니다.
여기서 궁금한 점은, 로그인된 사용자의 정보를 표시하거나 비교할때는 필연적으로

var authState = await _authState.GetAuthenticationStateAsync();
var user = authState.User;
var name = user.Name;

이런식으로 활용해야하지 않나요?
AuthorizeView에 따라 다른 View가 보여지기는 하지만, 그건 권한에 따라 View를 달리하는 용도고…
로그인된 정보를 표시하거나 활용하는 방법은 GetAuthenticationStateAsync를 호출해서 유저 정보를 가져올 수 밖에 없는거죠?


3항목 확인 결과 사내 시스템을 개발하면서 로그인의 귀차니즘을 줄여보고자 그렇게 의도한 것이긴 한데... 세션 스토리지를 활용하는 방안 또는 서버단에서 토큰을 관리하는 방법 등 다른 방법을 생각해보긴 해야할 것 같습니다..

결론.

수정될 부분이 많고, 더 공부할 부분도 많이 보이네요.
코드 리뷰 너무너무 감사합니다. :heart_eyes:

4 Likes

엉터리인 부분이 많아요! 가려서 보셔야 합니다!ㅋㅋ
더 개선되면 푸시해놓겠습니다.

2 Likes

원래 그런데서 쓸만한거 기워쓰는게 개발자 아니겠습니까 XD
+++ 추가 작업도 미리 감사드립니다.
++++ 참, 저도 별 달았습니다! 잘부탁합니다, 감사합니다.

2 Likes

스타 하나 걸겠습니다! :smiley:

3 Likes

1스타 맛있게 냠냠하겠습니다;;ㅋㅋ

개인적으로는 @BigSquare 님의 기여를 받아서 정답을 보고싶어요…
딱 봐도 한눈에 “이것이 인증이고 권한관리이다!” 하는 소스코드가 나올거 같습니다…

2 Likes

개인적으로 JWT 이론만 알고 있고
C#에서 구현된 코드를 본 적이 없어서 매우 관심 있어하는 부분입니다!
한번에 정답을 아는것보다 고쳐나가면서 발전되는 과정을 지켜보고싶네요!

3 Likes

그 방식을 쓰실 것이면, <CascadingAuthenticationState>를 App.razor 에서 지우셔도 됩니다.

안 지우실 것이면, 사용자 정보가 필요한 곳에서 매개 변수로 받으시며 되구요.

[CascadingParameter]
public Task<AuthenticationState> AuthState {get; set;}
var authState = await AuthState;
var user = authState.User;
var name = user.Name;

닷넷 문서는 후자를 권고하는데, 그건 내부 구현이 거기에 잘 어울리기 때문입니다.
제 생각은 닷넷과 패턴을 일치시키는 게 좋지 않을까합니다.


중요한 부분을 빼먹었네요.

<Authorized> 요소는 AuthenticationState 객체를 context 변수로 제공합니다.
RenderFragment<T> 를 다룰 때 처럼요.

//...
<Authorized>
Email : @context.User.FindFirst(System.Security.Claims.ClaimTypes.Name)
</Authorized>
// 

유저 정보를 가지고 뭔가를 처리하는 로직 없이, 단순하게 보여주기만 하는 용도라면, 이게 제일 깔끔합니다.


블레이저 서버의 코드는 서버에서 실행됩니다.
전에도 말씀드렸지만, 인증처리를 미들웨어가 하냐 레이저 컴포넌트가 하냐의 차이 밖에 없습니다.

4 Likes

참고로, 저는 가급적 프로젝트 생성할 때 Asp.Net Core Identity 를 사용하도록 설정합니다.

인증 자체가 논리적인 고려 사항 보다 상황적인 고려 사항이 많기 때문에, 제가 아무리 고민해도 닷넷 팀보다 나을까하는 의구심을 떨 칠 수 없기 때문입니다. 코드량도 줄이고 안정성도 높이는 방법이죠.

그런 이유로, 세션관리 토큰 관리 등을 처리하는 코드를 사용하지 않았기 때문에, "이참에 알아 본다"고 말씀드린 것입니다.

그리고, FireBase 나 SupaBase 같은 백엔드 서비스의 인증을 사용하는 방식과도 유사하기 때문에 코드 패턴이 달라지지 않는다는 장점이 있습니다

특히 사내 게시판이 목적이면, 백엔드를 Supabase (공짜) 에 넘기고, 블레이저 WASM 으로 프론트 엔드만 구현하는 것이 효율적이지 않을까요?

블레이저 호스팅 서비스 정도만 놀고 있는 컴퓨터를 사내에 두면, 참~~ 간단하쥬? ^^

그리고, 블레이저 WASM 프로젝트 생성할 때, PWA 옵션을 키면, 접속할 때 마다 웹 어셈블리를 다운로드 받지 않아도 되기 때문에, 사내 내트워크 대역을 조금이라도 아낄 수 있겠죠.

3 Likes

얼마전 송도에서 발표할때 쓰려고 작성한 코드입니다.

JWT 인증 관련 blazor Wasm 그리고 서버 코드도 있습니다.

5 Likes

음… 사실 지금 권해주신 WASM+PWA와 SupaBase 사용하고,
인증도 ASP.NET 기본인증체계를 사용하면 저로서도 좋을 것 같긴 합니다…
다만, 지금 진행중인걸 다시 갈아엎기엔 시간과 노력이 조금 더 들어갈 것 같아서
하던걸 완료 짓는게 우선이라 생각이 되네요…

일단 만들어놓고, 그 다음 도전해보겠습니다 :slight_smile:

그리고 코드를 직접 보시고 리뷰해주시는 것도 시간과 노력이 들어갈텐데
기꺼이 댓글도 달아주셔서 감사합니다.

2 Likes

아래 부분과 관련해서는,

이 경우, ASP.NET 기본인증체계를 사용할 수 없습니다. 아니, 필요도 없습니다. ^^
Supabase가 이미 구현해서 API 를 제공하기 때문입니다.

즉, Supabase 는 인증 기능이 이미 완료된 Asp.Net Core 웹앱과 같습니다. 여기에, 관리자 화면까지 전부 다 구현이 되어 있고, 이미 배포까지 되어 있습니다.
백엔드는 할게 없습니다

프론트 엔드(WASM) 코드에서는 Supabase 가 응답해주는 JWT를 세션 스토리지에 저장하기만 하면 되는데, 이 또한 핸들러로 정의하면 자동으로 관리 됩니다.

따라서, AuthenticationStateProvider는 세션 저장소에 토큰이 있나 없나만 확인하면 됩니다.

저는 사실 이 부분에 대한 구현을 하고 있는데 브라우저가 제공하는 세션 저장소 이벤트를 사용하는 방법을 연구 중입니다.

2 Likes

혹시 supabase, wasm조합이 되면 첨부파일같은 사용자 업로드 파일은 어디에, 어떻게 저장해야하나요?

1 Like

Storage 라는 API가 있습니다.

사실, 무엇을 상상하시든 이미 다 있습니다.

심지어 깨톡 인증 서비스도 있습니다.
캐톡에서 접근키를 받고, Supabase 관리자 화면에서 붙여 넣기만 하면, 준비 끝입니다.

프론트엔드에서는 API만 호출하면 됩니다.

다만, API 문서가 좀 친절하지 않다는 거…

1 Like