Azure移动应用程序使用Xamarin.Forms进行自定义+ Facebook身份验证

时间:2016-10-26 14:52:15

标签: authentication xamarin.forms azure-mobile-services

我正在使用带有.NET后端的Xamarin Forms移动应用程序。我跟着this guide并成功设置了自定义身份验证,并在Startup.cs中进行了一次更改:

app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
        {
            SigningKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY"),
            ValidAudiences = new[] { Identifiers.Environment.ApiUrl },
            ValidIssuers = new[] { Identifiers.Environment.ApiUrl },
            TokenHandler = config.GetAppServiceTokenHandler()
        });

没有" if(string.IsNullOrEmpty(settings.HostName))"。否则,我在登录后总是未经授权处理所有请求。

服务器项目:

  1. 验证控制器

    public class ClubrAuthController:ApiController {     private readonly ClubrContext dbContext;     private readonly ILoggerService loggerService;

    public ClubrAuthController(ILoggerService loggerService)
    {
        this.loggerService = loggerService;
        dbContext = new ClubrContext();
    }
    
    public async Task<IHttpActionResult> Post(LoginRequest loginRequest)
    {
        var user = await dbContext.Users.FirstOrDefaultAsync(x => x.Email == loginRequest.username);
        if (user == null)
        {
            user = await CreateUser(loginRequest);
        }
    
        var token = GetAuthenticationTokenForUser(user.Email);
    
        return Ok(new
        {
            authenticationToken = token.RawData,
            user = new { userId = loginRequest.username }
        });
    }
    
    private JwtSecurityToken GetAuthenticationTokenForUser(string userEmail)
    {
        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, userEmail)
        };
    
        var secretKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY");
        var audience = Identifiers.Environment.ApiUrl;
        var issuer = Identifiers.Environment.ApiUrl;
    
        var token = AppServiceLoginHandler.CreateToken(
            claims,
            secretKey,
            audience,
            issuer,
            TimeSpan.FromHours(24)
            );
    
        return token;
    }
    

    }

  2. Startup.cs

        ConfigureMobileAppAuth(app, config, container);
        app.UseWebApi(config);
    }
    
    private void ConfigureMobileAppAuth(IAppBuilder app, HttpConfiguration config, IContainer container)
    {
        config.Routes.MapHttpRoute("ClubrAuth", ".auth/login/ClubrAuth", new { controller = "ClubrAuth" });
    
        app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
        {
            SigningKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY"),
            ValidAudiences = new[] { Identifiers.Environment.ApiUrl },
            ValidIssuers = new[] { Identifiers.Environment.ApiUrl },
            TokenHandler = config.GetAppServiceTokenHandler()
        });
    }
    
  3. 客户项目:

    MobileServiceUser user = await MobileClient.LoginAsync(loginProvider, jtoken);
    

    此外,我在azure门户中配置了Facebook提供程序,如here所述。 但它只有在我注释掉app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions(){...})时才有效;在Startup.cs中。 我缺少两种类型的身份验证同时工作?

2 个答案:

答案 0 :(得分:0)

由于您启用了应用服务身份验证/授权,因此已经验证了令牌。它会假设您的令牌结构,例如让受众和发布者与您的应用URL相同(默认情况下)。

app.UseAppServiceAuthentication()也会验证令牌,因为它是meant for local development。因此,在您的示例中,令牌将被验证两次。除了潜在的性能影响,这通常很好。但是,这意味着令牌必须在两个层上都通过验证,我怀疑情况并非如此,因此错误。

检查这一点的一种方法是检查令牌本身。在客户端应用程序中设置断点并获取从LoginAsync()获取的令牌,该令牌将成为该用户对象的一部分。然后前往http://jwt.io之类的服务,查看令牌内容的样子。我怀疑Facebook令牌与您为aud配置的iss具有不同的Identifiers.Environment.ApiUrlapp.UseAppServiceAuthentication()声明,而自定义令牌可能与您匹配{#1}} 39;在第一个代码段中重新使用该值。

如果这是成立的,那么你应该处于两个令牌都失败的状态。 Facebook令牌将通过托管验证但在本地中间件上失败,而自定义令牌将失败托管验证但传递本地中间件。

此处最简单的解决方案是在云中托管时删除app.UseAppServiceAuthentication()。您还需要确保拨打CreateToken()的电话使用基于云的网址作为受众和发布者。

对于发现此问题的其他人

  • 可以找到自定义身份验证的文档here
  • 可以找到应用服务身份验证/授权的一般概述here

答案 1 :(得分:-1)

您引用的代码仅适用于本地部署。对于Azure部署,您需要打开应用服务身份验证/授权 - 即使您没有配置身份验证提供程序(在自定义身份验证的情况下也不会这样做)。

查看我的书的第2章 - http://aka.ms/zumobook