簡體   English   中英

401 在 Xamarin.Forms 上未經 Azure b2c 授權

[英]401 Unauthorized with Azure b2c on Xamarin.Forms

我有一個 Xamarin.Forms 應用程序,用於連接到應用服務后端,我正在嘗試使用 Auzre B2C JWT 令牌進行身份驗證。

通過各種教程,我設法使用微軟帳戶進行 B2C 設置,並且我能夠創建用戶、更改密碼和生成訪問令牌。

我的下一步是將 [Authorize] 屬性添加到我的控制器並嘗試將該令牌傳遞給我的應用程序服務並授權用戶,但無論我嘗試什么,我的服務都會收到 401 Unauthorized 響應。

  • 我正在將 JWT 令牌添加到我的 HttpClient 的 Authorization 標頭中,並且它正在訪問服務。
  • 我可以將我的令牌粘貼到https://jwt.ms/ 中,它會正確地告訴我令牌中的內容。
  • 我已經實現了這段代碼,試圖找出問題所在。

startup.cs 中的 ConfigureServices 如下所示:

public void ConfigureServices(IServiceCollection services) {

            services.AddAuthentication(options => {                
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                .AddJwtBearer(options => {

                    options.Audience = Configuration["Authentication:AzureAd:ClientId"];

                    options.Events = new JwtBearerEvents {
                        OnAuthenticationFailed = AuthenticationFailed
                    };

                    options.Authority = $"https://{tenant name}.b2clogin.com/{tenant id}/{Configuration["Authentication:AzureAd:Policy"]}";

                    options.Events = new JwtBearerEvents {

                        OnAuthenticationFailed = ctx =>
                        {
                            ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
                            message += "From OnAuthenticationFailed:\n";
                            message += FlattenException(ctx.Exception);
                            return Task.CompletedTask;
                        },
                        OnChallenge = ctx =>
                        {
                            message += "From OnChallenge:\n";
                            ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
                            ctx.Response.ContentType = "text/plain";
                            return ctx.Response.WriteAsync(message);
                        },
                        OnMessageReceived = ctx =>
                        {
                            message = "From OnMessageReceived:\n";
                            ctx.Request.Headers.TryGetValue("Authorization", out var BearerToken);
                            if (BearerToken.Count == 0)
                                BearerToken = "no Bearer token sent\n";
                            message += "Authorization Header sent: " + BearerToken + "\n";
                            return Task.CompletedTask;
                        },
                        OnTokenValidated = ctx =>
                        {
                            Debug.WriteLine("token: " + ctx.SecurityToken.ToString());
                            return Task.CompletedTask;
                        }
                    };

                });

            services.AddMvc();
        }

配置看起來像這樣:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();

                IdentityModelEventSource.ShowPII = true;
            } else {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseAuthentication();
            app.UseMvc();
        }

而且我還將此調用添加到 AuthenticationFailed,因此我會知道我的身份驗證是否有效:


        Task AuthenticationFailed(AuthenticationFailedContext arg) {
            Console.WriteLine(arg.Exception.Message);
            return Task.FromResult(0);
        }

使用我當前的設置,我從服務器收到 401 錯誤,這是在它擊中 Startup.cs 中連接的 OnChallenge 事件之后。 根據上面的鏈接,這就是在向用戶返回 401 之前調用的內容,因此服務似乎正在接收正確的令牌並進行身份驗證,但也許我沒有設置正確的權限?

我不確定從哪里開始,但任何指導將不勝感激。

編輯:

正如下面的評論中提到的,我能夠使用通過我的應用程序登錄后生成的訪問令牌來卷曲我的網站,如下所示:

curl https://mywebsite.azurewebsites.net/api/Values -i --header "Authorization: Bearer [TOKEN]"

這似乎沒有問題,所以這似乎與我如何通過我的應用程序調用控制器有關,而不是身份驗證本身。

編輯2(解決方案):

因此,根據 Edit 1,我是正確的,因為這正是我將令牌添加到授權標頭的方式。 這不是我最輝煌的時刻,但我並沒有針對包含我的訪問令牌的聲明調用 .Value。 我只是在聲明本身上調用 .ToString(),所以“令牌”實際上是整個聲明文本“訪問令牌:”。 在調試我的服務時,我並沒有想太多,因為我沒有意識到它不應該有那個文本。

一旦我糾正了這個問題,服務就開始按預期工作。

所以,最后,我想這一切都按預期進行。 事實上,我沒有發送預期的令牌,所以我......未經授權。

根據要求,我必須更改的代碼行是這樣的:

因此,這不會 100% 適用於大多數人,因為我使用的是一個名為 CSLA 的業務庫,但無論如何這個想法都是一樣的。

在我的 b2c 調用返回令牌后,我將它存儲在 CSLA 庫中內置的 ApplicationContext.User.Identity 中。 這允許我稍后獲得訪問令牌聲明。 重要的部分是我將令牌存儲在某個地方,以便稍后我想將其添加到授權標頭時可以訪問它。

后來,當我使用 httpclient 進行調用時,我需要獲取該令牌,因此最初我是這樣做的:

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ((ClaimsIdentity)ApplicationContext.User.Identity).Claims.FirstOrDefault(c => c.Type == "AccessToken") .ToString() );

這不正確。 這是發送“令牌”作為值“訪問令牌:[令牌值]。本質上,它是將“訪問令牌”字樣添加到我需要進行身份驗證的令牌中,但失敗了,因為“訪問令牌”字樣實際上不應該是您用於身份驗證的令牌的一部分。

在我改變我的電話之后:

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ((ClaimsIdentity)ApplicationContext.User.Identity).Claims.FirstOrDefault(c => c.Type == "AccessToken") .Value );

它開始只獲取令牌值,當它被添加到授權標頭時,它工作得很好。

編輯 2 解釋了我的問題的答案。

我沒有將令牌正確添加到授權標頭中,因此該服務無法對令牌進行身份驗證,或者更確切地說,它認為令牌無效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM