कई JWT बियरर प्रमाणीकरण का उपयोग करें


87

क्या ASP.NET Core 2 में कई JWT टोकन जारीकर्ताओं का समर्थन करना संभव है? मैं बाहरी सेवा के लिए एक एपीआई प्रदान करना चाहता हूं और मुझे JWT टोकन के दो स्रोतों का उपयोग करने की आवश्यकता है - फायरबेस और कस्टम जेडब्ल्यूटी टोकन जारीकर्ता। ASP.NET कोर में मैं बियरर स्कीम योजना के लिए JWT प्रमाणीकरण सेट कर सकता हूं, लेकिन केवल एक प्राधिकरण के लिए:

  services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://securetoken.google.com/my-firebase-project"
            options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = "my-firebase-project"
                    ValidateAudience = true,
                    ValidAudience = "my-firebase-project"
                    ValidateLifetime = true
                };
        }

मेरे पास कई जारीकर्ता और दर्शक हो सकते हैं, लेकिन मैं कई प्राधिकरण स्थापित नहीं कर सकता।


1
AFAIK आप JWT में किसी भी संख्या में गुण जोड़ सकते हैं। तो, JWT में दो जारीकर्ता नामों को दर्ज करने से आपको कोई रोक नहीं सकता है। समस्या यह है कि आपके एप्लिकेशन को दोनों कुंजियों को जानना होगा, यदि प्रत्येक जारीकर्ता हस्ताक्षर करने के लिए एक अलग कुंजी का उपयोग कर रहा हो।
टिम बेगेलेसेन

जवाबों:


186

आप पूरी तरह से प्राप्त कर सकते हैं कि आप क्या चाहते हैं:

services
    .AddAuthentication()
    .AddJwtBearer("Firebase", options =>
    {
        options.Authority = "https://securetoken.google.com/my-firebase-project"
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "my-firebase-project"
            ValidateAudience = true,
            ValidAudience = "my-firebase-project"
            ValidateLifetime = true
        };
    })
    .AddJwtBearer("Custom", options =>
    {
        // Configuration for your custom
        // JWT tokens here
    });

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();
    });

चलो अपने कोड और उस एक के बीच के अंतर से गुजरते हैं।

AddAuthentication कोई पैरामीटर नहीं है

यदि आप एक डिफ़ॉल्ट प्रमाणीकरण योजना सेट करते हैं, तो हर एक अनुरोध पर प्रमाणीकरण मिडलवेयर डिफ़ॉल्ट प्रमाणीकरण योजना से जुड़े प्रमाणीकरण हैंडलर को चलाने का प्रयास करेगा। चूँकि अब हमारे पास दो ओपेसिबल प्रमाणीकरण योजनाएँ हैं, इसलिए उनमें से एक को चलाने का कोई मतलब नहीं है।

का एक और अधिभार का उपयोग करें AddJwtBearer

AddXXXप्रमाणीकरण जोड़ने के लिए हर एक विधि में कई अतिभार होते हैं:

अब, क्योंकि आप एक ही प्रमाणीकरण विधि का दो बार उपयोग करते हैं, लेकिन प्रमाणीकरण योजनाएँ अद्वितीय होनी चाहिए, आपको दूसरे अधिभार का उपयोग करने की आवश्यकता है।

डिफ़ॉल्ट नीति को अपडेट करें

चूँकि अनुरोधों को स्वचालित रूप से प्रमाणित नहीं किया जाएगा, इसलिए [Authorize]कुछ कार्यों पर विशेषताएँ डालने से अनुरोध अस्वीकृत HTTP 401हो जाएंगे और जारी किए जाएंगे।

के बाद से वह नहीं है कि हम क्या चाहते हैं, क्योंकि हम प्रमाणीकरण संचालकों अनुरोध प्रमाणित करने के लिए एक मौका देना चाहते हैं, हम दोनों को दर्शाते हुए प्राधिकरण सिस्टम का डिफॉल्ट नीति में बदलाव Firebaseऔर Customप्रमाणीकरण स्कीम किया जाना चाहिए की कोशिश की अनुरोध प्रमाणित करने के लिए।

यह आपको कुछ कार्यों पर अधिक प्रतिबंध लगाने से नहीं रोकता है; [Authorize]विशेषता एक है AuthenticationSchemesसंपत्ति है कि आप ओवरराइड करने के लिए जो प्रमाणीकरण स्कीम मान्य हैं अनुमति देता है।

यदि आपके पास अधिक जटिल परिदृश्य हैं, तो आप नीति-आधारित प्राधिकरण का उपयोग कर सकते हैं । मुझे लगता है कि आधिकारिक दस्तावेज महान है।

आइए कल्पना करें कि कुछ क्रियाएं केवल JWT टोकन के लिए उपलब्ध हैं जो Firebase द्वारा जारी किए गए हैं और एक विशिष्ट मूल्य के साथ एक दावा होना चाहिए; आप इसे इस तरह से कर सकते हैं:

// Authentication code omitted for brevity

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();

        options.AddPolicy("FirebaseAdministrators", new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase")
            .RequireClaim("role", "admin")
            .Build());
    });

फिर आप [Authorize(Policy = "FirebaseAdministrators")]कुछ कार्यों पर उपयोग कर सकते हैं ।

नोट करने के लिए एक अंतिम बिंदु: यदि आप AuthenticationFailedघटनाओं को पकड़ रहे हैं और कुछ भी लेकिन पहली AddJwtBearerनीति का उपयोग कर रहे हैं , तो आप यह देख सकते हैं कि IDX10501: Signature validation failed. Unable to match key...यह सिस्टम के कारण होता है AddJwtBearerजब तक कि यह मैच नहीं हो जाता। त्रुटि को आमतौर पर नजरअंदाज किया जा सकता है।


4
क्या यह आवश्यक है कि हेडर का मूल्य फायरबेस या कस्टम समाधान से बदला जाए? अर्थात। इसके बजाय Authorization : Bearer <token>हेडर Authorization : Firebase <token>उदाहरण के लिए होना चाहिए ? जब इस समाधान की कोशिश की गई तो मुझे त्रुटि मिली: "कोई भी प्रमाणीकरण हैंडलर योजना 'बियरर' के लिए पंजीकृत नहीं है।"
रश फ्रिसबी

4
नहीं, हेडर को बदलने की आवश्यकता नहीं है। त्रुटि संदेश बताता है कि आप एक गैर-मौजूद प्रमाणीकरण योजना (बियरर) का उल्लेख कर रहे हैं। हमारे उदाहरणों में, दो पंजीकृत योजनाएं फायरबेस और कस्टम हैं, जो .AddJwtBearerविधि कॉल के पहले तर्क हैं।
मिकाल डेरीए

5
नमस्ते। बस इसी समाधान की तलाश में था। दुर्भाग्य से मुझे एक "कोई प्रमाणीकरण नहीं मिल रहा है किन्हें निर्दिष्ट किया गया था, और कोई DefaultChallengeScheme" अपवाद नहीं मिला। Options.DefaultPolicy ठीक है। कोई विचार?
terjetyl

11
यह एक बहुत ही उपयोगी उत्तर था, और जो कुछ मैंने देखा है, उसे पूरे स्थान पर एक साथ रखा।
एरन डब्ल्यू।

2
@TylerOhlsen जो सही नहीं है; जबकि यह आपके द्वारा वर्णित मामले में उपयोग किया जाएगा, यह केवल एक ही नहीं है। यदि आप एंडपॉइंट स्तर पर एक प्राधिकरण आवश्यकता को निर्दिष्ट नहीं करते हैं, तो इसका उपयोग किया जाएगा, लेकिन एमवीसी नियंत्रकों और / या कार्यों को एक खाली [Authorize]विशेषता के साथ सजाएं।
मिकाल डेर्री

4

यह मिकाइल डेर्री के उत्तर का विस्तार है।

हमारे ऐप में एक कस्टम प्राधिकरण आवश्यकता है जिसे हम आंतरिक स्रोत से हल करते हैं। हम Auth0 का उपयोग कर रहे थे, लेकिन OpenID का उपयोग करके Microsoft खाता प्रमाणीकरण पर स्विच कर रहे हैं। यहाँ हमारे ASP.Net Core 2.1 स्टार्टअप से थोड़ा संपादित कोड है। भविष्य के पाठकों के लिए, यह निर्दिष्ट संस्करणों के लिए इस लेखन के रूप में काम करता है। कॉलर OpenID से id_token का उपयोग करता है आने वाले अनुरोधों पर एक बियरर टोकन के रूप में पारित किया जाता है। आशा है कि यह किसी अन्य व्यक्ति को पहचान प्राधिकरण रूपांतरण करने की कोशिश कर रहा है, क्योंकि इस प्रश्न और उत्तर ने मेरी मदद की।

const string Auth0 = nameof(Auth0);
const string MsaOpenId = nameof(MsaOpenId);

string domain = "https://myAuth0App.auth0.com/";
services.AddAuthentication()
        .AddJwtBearer(Auth0, options =>
            {
                options.Authority = domain;
                options.Audience = "https://myAuth0Audience.com";
            })
        .AddJwtBearer(MsaOpenId, options =>
            {
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateAudience = true,
                    ValidAudience = "00000000-0000-0000-0000-000000000000",

                    ValidateIssuer = true,
                    ValidIssuer = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",

                    ValidateIssuerSigningKey = true,
                    RequireExpirationTime = true,
                    ValidateLifetime = true,
                    RequireSignedTokens = true,
                    ClockSkew = TimeSpan.FromMinutes(10),
                };
                options.MetadataAddress = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0/.well-known/openid-configuration";
            }
        );

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes( Auth0, MsaOpenId )
        .Build();

    var approvedPolicyBuilder =  new AuthorizationPolicyBuilder()
           .RequireAuthenticatedUser()
           .AddAuthenticationSchemes(Auth0, MsaOpenId)
           ;

    approvedPolicyBuilder.Requirements.Add(new HasApprovedRequirement(domain));

    options.AddPolicy("approved", approvedPolicyBuilder.Build());
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.