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:

10개의 좋아요

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

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

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

  1. IsAuthenticated 도 불필요.

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

  1. 로컬 저장소

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

6개의 좋아요

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

2개의 좋아요

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

4개의 좋아요

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

2개의 좋아요

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개의 좋아요

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

2개의 좋아요

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

2개의 좋아요

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

3개의 좋아요

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

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

2개의 좋아요

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

3개의 좋아요

그 방식을 쓰실 것이면, <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개의 좋아요

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

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

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

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

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

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

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

3개의 좋아요

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

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

5개의 좋아요

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

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

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

3개의 좋아요

아래 부분과 관련해서는,

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

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

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

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

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

2개의 좋아요

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

1개의 좋아요

Storage 라는 API가 있습니다.

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

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

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

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

1개의 좋아요