2016-10-08 5 views
4

일부 데이터 저장소에 Firebase를 사용하는 프로젝트에서 작업하며 클라이언트는 C# .NET으로 서버를 구현하도록 요청합니다. 우리는 서버에 REST 엔드 포인트를 설정하여 클라이언트가 몇 가지 목적 (예 : 서버에서만 실행할 수있는 알고리즘 실행)을 위해 클라이언트와 통신 할 수 있도록합니다.Firebase .NET 토큰 검증

중포 기지는 여기에 명시된 바와 같이, ID를 토큰을 통해 사용자를 식별하는 것이 좋습니다 : https://firebase.google.com/docs/auth/server/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library 토큰 인증을 지원하는 공식 .NET 중포 기지 서버 SDK가 없기 때문에, 우리는 제 3 자 JWT 라이브러리를 사용에 의존 한

이렇게하려면 : https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet

Firebase 설명서에 지정된대로 우리는 먼저 서버로 토큰을 보내고 있습니다. 토큰에 몇 가지 필드를 확인 후, 우리는 우리가 오랫동안 문서 및 StackOverflow의를 통해 주변의 파고 봤는데 https://www.googleapis.com/robot/v1/metadata/x509/[email protected]

에서 공개 키를 잡기 위해 kid 필드를 사용하고 있지만 우리는 찾을 수 없습니다 이 공개 키를 사용하여 Firebase 문서에 지정된대로 다음을 수행하십시오.

마지막으로 ID 토큰이 토큰의 아동 클레임에 해당하는 개인 키로 서명되었는지 확인하십시오. https://www.googleapis.com/robot/v1/metadata/x509/[email protected]에서 공개 키를 가져 와서 JWT 라이브러리를 사용하여 서명을 확인하십시오.

Firebase 설명서는 실제로 이에 대한 설명을 제공하지 않으며 사용중인 라이브러리에 대한 설명서도 제공하지 않습니다. 그래서 우리는 토큰이 모두 공개 키인 경우 개인 키에 의해 서명 된 토큰임을 검증 할 수있는 방법에 대한 기본 아이디어조차 얻을 수 없었습니다.

토큰이 올바른 개인 키로 실제로 서명되었는지 확인하는 가장 좋은 방법은 무엇입니까?

답변

5

당신은 가장 검증 수행 할 System.IdentityModel.Tokens.Jwt Nuget 패키지를 활용하여 다음과 같이 뭔가를 수행하여 토큰 유효성 검사를 수행 할 수 있어야한다 : 샘플 프로그램에 대한 사용 문의

class Program { 
    static HttpClient client = new HttpClient(); 
    static void Main() { RunAsync().Wait(); } 

    static async Task RunAsync() { 
    string encodedJwt = "[TOKEN_TO_BE_VALIDATED]"; 
    // 1. Get Google signing keys 
    client.BaseAddress = new Uri("https://www.googleapis.com/robot/v1/metadata/"); 
    HttpResponseMessage response = await client.GetAsync(
     "x509/[email protected]"); 
    if (!response.IsSuccessStatusCode) { return; } 
    var x509Data = await response.Content.ReadAsAsync<Dictionary<string, string>>(); 
    SecurityKey[] keys = x509Data.Values.Select(CreateSecurityKeyFromPublicKey).ToArray(); 
    // 2. Configure validation parameters 
    const string FirebaseProjectId = "[FIREBASE_PROJECT_ID]"; 
    var parameters = new TokenValidationParameters { 
     ValidIssuer = "https://securetoken.google.com/" + FirebaseProjectId, 
     ValidAudience = FirebaseProjectId, 
     IssuerSigningKeys = keys, 
    }; 
    // 3. Use JwtSecurityTokenHandler to validate signature, issuer, audience and lifetime 
    var handler = new JwtSecurityTokenHandler(); 
    SecurityToken token; 
    ClaimsPrincipal principal = handler.ValidateToken(encodedJwt, parameters, out token); 
    var jwt = (JwtSecurityToken)token; 
    // 4.Validate signature algorithm and other applicable valdiations 
    if (jwt.Header.Alg != SecurityAlgorithms.RsaSha256) { 
     throw new SecurityTokenInvalidSignatureException(
     "The token is not signed with the expected algorithm."); 
    } 
    } 
    static SecurityKey CreateSecurityKeyFromPublicKey(string data) { 
    return new X509SecurityKey(new X509Certificate2(Encoding.UTF8.GetBytes(data))); 
    } 
} 

목록 :

using System; 
using System.Collections.Generic; 
using System.IdentityModel.Tokens.Jwt; 
using System.Linq; 
using System.Net.Http; 
using System.Security.Claims; 
using System.Security.Cryptography.X509Certificates; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.IdentityModel.Tokens; 
+0

SecurityTokenSIgnatureKeyNotFoundException을 가져 오는 중입니다. 이 부분을 더 깊이 파고들 것입니다. 출발점을 알려줘서 고마워요! 이 솔루션과 함께 작동하게되면 나는 대답을 받아 들일 것입니다. – nolasaint

+0

제공된 보안 키가 JWT가 사용하도록 선언 한 보안 키와 일치하지 않는 경우 발생합니다. [jwt.io] (https://jwt.io/)에서 토큰을 디코딩하면 헤더에'kid' 속성이있을 것입니다. 값은 Google에서 가져온 목록에서 반환 된 인증서 중 하나와 일치해야합니다. 그렇지 않으면 예외가 설명됩니다. –

+0

귀하의 솔루션을 구현하고 동일한 예외가 발생했습니다. https://www.googleapis.com/robot/v1/metadata/x509/[email protected]에서 인증서와 대조되는 내 토큰을 확인했으며 4 중 하나와 일치합니다. 4 개의 인증서가로드되었습니다. 유효성을 검사 할 때 SecurityTokenSIgnatureKeyNotFoundException이 throw됩니다.어떤 아이디어? –

1

나 같은 다른 Newtonsoft.JSON 라이브러리를 사용하고 Microsoft를 가져 오지 않으려면 다음 중 하나를 시도하십시오. https://gist.github.com/saltyJeff/41029c9facf3ba6159ac019c1a85711a

Verify(string token)을 사용하면 토큰이 유효한지 비동기식으로 확인합니다. 유효한 경우 사용자의 고유 식별자를 반환하고, 유효하지 않은 경우 null을 반환합니다.

관련 문제