Azure移动应用和身份验证

时间:2016-11-09 16:16:47

标签: c# azure authentication xamarin azure-mobile-services

我正在编写移动应用程序,目前它只是添加了自定义身份验证的待办事项列表快速启动应用程序。我有相关的Xamarin Forms应用程序。

从App我能够使用LoginAsync方法登录,我的网站返回一个令牌并显示我登录的用户名,但后续调用显示我未获得授权。

经过一些调试后,我可以看到请求到达Web服务器时带有X-ZUMO-AUTH标头和值中的标记,但是我可以看到用户似乎没有被填充并且调用GetAllTodoItems方法返回401:Unauthorized。

在网站的启动代码中,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()
        });
    }

我有一个帐户控制器类:

[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;
    }
}

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();
    }
    ...
    ...
}

在从Xamarin App调用查询方法时,即使X-ZUMO-AUTH位于头文件中并且包含登录方法发出的正确令牌,它也会返回401。

我之前是否遗漏了某些内容或有任何人遇到此问题 - 我们将不胜感激任何帮助?

2 个答案:

答案 0 :(得分:0)

您是否在App Service中启用了身份验证/授权?没有它,令牌永远不会被解码。

这是最常见的问题。

答案 1 :(得分:0)

挖掘后我发现了这个问题,最初有一个配置问题 - 上面的评论有帮助谢谢。受众和发行人必须与您的天蓝色网站相匹配,包括尾部斜杠。

配置更正后的问题是,从我的应用程序正确传递的令牌未在服务器端进行处理,因此所有授权区域都超出范围。这是因为ConfigureMobileApp方法中的调用顺序。我在 app.UseAppServiceAuthentication 方法之前调用 app.UseWebApi 方法,更改订单后再次测试令牌。

我现在工作的虚拟网站有以下内容:

    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);
    }