简体   繁体   English

Azure移动应用程序和身份验证

[英]Azure Mobile App and Authentication

I have a Mobile App I am writing, at present it is simply the To Do Item list quick start application with custom Authentication added. 我有一个正在编写的移动应用程序,目前它只是添加了自定义身份验证的“待办事项”列表快速入门应用程序。 I have the associated Xamarin Forms app. 我有关联的Xamarin Forms应用程序。

From the App I am able to login using the LoginAsync method, my website returns a token and shows the username I am logging in as, but subsequent calls suggest I am not authorised. 从应用程序中,我可以使用LoginAsync方法登录,我的网站返回一个令牌,并显示我登录时使用的用户名,但随后的调用表明我未被授权。

After a bit of debugging, I can see that the request arrives at the web server with the X-ZUMO-AUTH header and the token in the value, but I can see that the User does not seem to be populated and the call to the GetAllTodoItems method is returned as 401:Unauthorized. 经过一些调试后,我可以看到请求到达了带有X-ZUMO-AUTH标头和值中的令牌的Web服务器,但是我可以看到用户似乎没有被填充,并且对GetAllTodoItems方法返回为401:未经授权。

In the startup code for the website, the ConfigureMobileApp contains the following: 在网站的启动代码中,ConfigureMobileApp包含以下内容:

    app.UseWebApi(config);

    if (string.IsNullOrEmpty(settings.HostName))
    {
        // This middleware is intended to be used locally for debugging. By default, HostName will
        // only have a value when running in an App Service application.
        app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
        {
            SigningKey = ConfigurationManager.AppSettings["SigningKey"],
            ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
            ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
            TokenHandler = config.GetAppServiceTokenHandler()
        });
    }

I have an account controller class: 我有一个帐户控制器类:

[Route(".auth/login/custom")]
public class AccountController : ApiController
{
    private static string URL = "https://myapidev.azurewebsites.net/";
    private static string KEY = "FC31EB8CAAAAAA9D74EEE3613A7A08CA65CB1ACAA8CEFF82A5B5E915625B31D";

    public AccountController()
    {

    }
    [HttpPost]
    public IHttpActionResult Post([FromBody] LoginUser assertion)
    {
        if (isValidAssertion(assertion))
        {
            JwtSecurityToken token = AppServiceLoginHandler.CreateToken(new Claim[] { new Claim(JwtRegisteredClaimNames.Sub, assertion.username) },
                ConfigurationManager.AppSettings["SigningKey"],
                ConfigurationManager.AppSettings["ValidAudience"],
                ConfigurationManager.AppSettings["ValidIssuer"],
                TimeSpan.FromHours(24));

            return Ok(new LoginResult()
            {
                authenticationToken = token.RawData,
                user = new LoginResultUser() { userId = assertion.username }
            });
        }
        else // user assertion was not valid
        {
            return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid Request"));
        }
    }

    private bool isValidAssertion(LoginUser assertion)
    {
        return assertion != null;
    }
}

The TodoItemController contains the following: TodoItemController包含以下内容:

[Authorize]
[MobileAppController]
public class TodoItemController : TableController<TodoItem>
{
    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);
        EducaterAPIDevContext context = new EducaterAPIDevContext();
        DomainManager = new EntityDomainManager<TodoItem>(context, Request);

        //// Get the SID of the current user.
        //var claimsPrincipal = this.User as ClaimsPrincipal;
        //string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;
    }

    // GET tables/TodoItem
    public IQueryable<TodoItem> GetAllTodoItems()
    {
        return Query();
    }
    ...
    ...
}

On calling the query method from the Xamarin App, it returns with 401 even though the X-ZUMO-AUTH is in the headers and contains the correct token issued by the login method. 从Xamarin App调用查询方法时,即使X-ZUMO-AUTH在标头中并包含由登录方法发出的正确令牌,它也会返回401。

Have I missed something or has anyone come across this issue before - any help would be appreciated? 我错过了什么吗?或者之前有人遇到过这个问题-我们将不胜感激?

Have you turned on Authentication/Authorization in your App Service? 您是否在App Service中启用了身份验证/授权? Without it, the token will never be decoded. 没有它,令牌将永远不会被解码。

This is the most common issue. 这是最常见的问题。

After digging I found the issue, initially there was a configuration issue - the above comments helped thanks. 挖掘之后,我发现了问题,最初是配置问题-上面的评论有所帮助。 The Audiences and Issuers must match your azure site including including the trailing slash. 受众和发行者必须与您的蔚蓝站点相匹配,包括末尾的斜杠。

The issue once the configuration had been corrected was that the token which is passed correctly from my App did not get processed at the server side so all Authorized areas where out-of-bounds. 一旦更正了配置,问题就在于从服务器端正确处理了从我的应用程序正确传递的令牌,因此所有授权区域都越界。 This was because of the order of calls in the ConfigureMobileApp method. 这是因为ConfigureMobileApp方法中的调用顺序。 I was calling the app.UseWebApi method before the app.UseAppServiceAuthentication method, changing the order suddenly had the token being tested again. 我打电话的app.UseAppServiceAuthentication方法之前app.UseWebApi方法,更改订单突然有了令牌再次进行测试。

The dummy site I have working now has the following: 我现在工作的虚拟站点具有以下内容:

    public static void ConfigureMobileApp(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        //For more information on Web API tracing, see http://go.microsoft.com/fwlink/?LinkId=620686 
        SystemDiagnosticsTraceWriter traceWriter = config.EnableSystemDiagnosticsTracing();

        new MobileAppConfiguration()
            .UseDefaultConfiguration()
            .MapApiControllers()
            .ApplyTo(config);

        config.MapHttpAttributeRoutes();

        // Use Entity Framework Code First to create database tables based on your DbContext
        //Database.SetInitializer(new EducaterAPIDevInitializer());

        // To prevent Entity Framework from modifying your database schema, use a null database initializer
        // Database.SetInitializer<EducaterAPIDevContext>(null);

        MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();
        if (string.IsNullOrEmpty(settings.HostName))
        {
            var options = new AppServiceAuthenticationOptions
            {
                SigningKey = ConfigurationManager.AppSettings["SigningKey"],
                ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
                ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
                TokenHandler = config.GetAppServiceTokenHandler()
            };
            app.UseAppServiceAuthentication(options);
        }
        app.UseWebApi(config);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM