2016-08-14 32 views
2

我正在用.net核心web api後端在iOS應用上實現Facebook登錄。我可以驗證使用本機iOS sdk與.net後端創建的Facebook jwt令牌嗎?

  1. 我使用客戶端ID和祕密在Facebook中創建了應用程序。
  2. 我加入iOS和網頁,以我的應用程序
  3. 的iOS應用連接成功並aquires令牌
  4. 我加入了app.UseFacebook代碼我startup.cs與應用程序ID等
  5. 配置它
  6. 我加入了授權屬性的動作,我限制訪問
  7. 我打電話從iOS的這個網頁API動作以HTTPS GET,並添加一個HTTP頭授權承載(令牌我從Facebook收購)

獲得退貨狀態代碼401就好像我的令牌無效。我想知道iOS令牌是否可以與網頁應用一起使用?我爲我的Facebook應用程序配置了2個。

+0

請回復您的答案...其他人(如我)可能會受益T hanks – Stephane

+0

@Stephane,完成!對於慢響應抱歉。你是如何繼續實施的?我想和你的朋友進行比較 – ProgrammerGuy

回答

1

ASP.NET Security repo包含不同的認證中間件,您可以在其中找到如何檢查和驗證jwt令牌並使用聲明創建標識。看看FacebookHandler.cs如果你需要Facebook智威湯遜驗證

+0

我已經在使用這些庫,但是你給了我一個想法,在我的調試中包含.net框架源代碼,以查看引擎蓋下發生了什麼,並查看屬性是如何生成的它通過圖層,調用什麼方法以及爲什麼。謝謝! – ProgrammerGuy

+0

鏈接被破壞 – Softlion

+0

@Softlion固定。他們現在使用'dev'分支名稱而不是'master'(如果發現其他鏈接斷開,可能是同一個問題) – Set

5

我不確定這是否是正確的方式來做到這一點,但我的實施工作。

的工作流,

  • iOS應用使用Facebook SDK
  • iOS應用使用Facebook訪問令牌
  • .NET創建在.NET後端用戶得到一個Facebook訪問令牌後端驗證Facebook訪問令牌是否有效並下載用戶數據
  • .NET後端創建一個jwt載體令牌並將其返回給iOS應用程序
  • iOS應用程序使用jwt載體toke調用.NET後端N的授權HTTP標題

我檢查了Facebook訪問令牌是有效的,通過調用https://graph.facebook.com - 是指:任務VerifyAccessToken(字符串email,字符串的accessToken)

AccountController.cs

[AllowAnonymous, HttpPost("[action]")] 
public async Task<ActionResult> FacebookAuth([FromBody] ExternalLoginModel model) 
{ 
    try 
    { 
     await _interactor.VerifyAccessToken(model.Email, model.Token); 

     var result = await _interactor.SignInWithFacebook(model.Email); 

     return Ok(result);    
    } 
    catch (ValidationException ex) 
    { 
     return BadRequest(ex.Message.ErrorMessage(Strings.ValidationException)); 
    } 
} 

[AllowAnonymous, HttpPost("[action]")] 
public async Task<ActionResult> CreateAccountWithFacebook(AccountModel account, string token) 
{ 
    try 
    { 
    await _interactor.VerifyAccessToken(account.Email, token); 

    if (ModelState.IsValid) 
    {    
     var result = await _interactor.CreateFacebookLogin(account); 

     return Ok(result); 
    } 

    return BadRequest(ModelState); 
    } 
    catch (ValidationException ex) 
    { 
    return BadRequest(ex.Message.ErrorMessage(Strings.ValidationException)); 
    } 
} 

調用Facebook的圖表服務,以驗證訪問令牌是有效的

public async Task<FacebookMeResponse> VerifyAccessToken(string email, string accessToken) 
{ 
    if (string.IsNullOrEmpty(accessToken)) 
    { 
     throw new ValidationException("Invalid Facebook token"); 
    } 

    string facebookGraphUrl = "https://graph.facebook.com/me?fields=cover,age_range,first_name,location,last_name,hometown,gender,birthday,email&access_token=" + accessToken; 
    WebRequest request = WebRequest.Create(facebookGraphUrl); 
    request.Credentials = CredentialCache.DefaultCredentials; 

    using (WebResponse response = await request.GetResponseAsync()) 
    { 
     var status = ((HttpWebResponse)response).StatusCode; 

     Stream dataStream = response.GetResponseStream(); 

     StreamReader reader = new StreamReader(dataStream); 
     string responseFromServer = reader.ReadToEnd(); 
     var facebookUser = JsonConvert.DeserializeObject<FacebookMeResponse>(responseFromServer); 

     bool valid = facebookUser != null && !string.IsNullOrWhiteSpace(facebookUser.Email) && facebookUser.Email.ToLower() == email.ToLower(); 
     facebookUser.PublicProfilePhotoUrl = "http://graph.facebook.com/" + facebookUser.Id + "/picture"; 

     if (!valid) 
     { 
      throw new ValidationException("Invalid Facebook token"); 
     } 

     return facebookUser; 
    } 
} 

爲您的中間件創建一個jwt記載令牌,iOS應用將使用jwt記載令牌來調用您的中間件。NET的API(它不會使用Facebook的access_token)

public async Task<FacebookResponse> SignInWithFacebook(string email) 
{ 
    var claims = new List<Claim>(); 

    var user = await _userManager.FindByEmailAsync(email); 

    var identity = new ClaimsIdentity(claims, "oidc"); 

    var jwtBearerToken= Guid.NewGuid().ToString(); 
    var properties = new AuthenticationProperties(); 
    properties.Items.Add(".Token.access_token", jwtBearerToken); 

    await _signInManager.SignInAsync(user, properties, "oidc"); 

    var principal = await _signInManager.CreateUserPrincipalAsync(user); 

    var token = new Token(); 
    token.Key = jwtBearerToken; 
    token.Expiry = DateTime.UtcNow.AddMinutes(30); 
    token.UserId = user.Id; 
    token.TokenType = "FacebookLogin"; 

    await _tokensRepository.Save(token); 
    var result = _signInManager.IsSignedIn(principal); 

    return new FacebookResponse("success", result, jwtBearerToken); 
} 

創建一個用戶,如果它不存在

public async Task<FacebookResponse> CreateFacebookLogin(AccountModel model) 
{ 
    User user = await _userManager.FindByEmailAsync(model.Email); 

    if (user == null) 
    { 
     var createResult = await _userManager.CreateAsync(_mapper.Map<AccountModel, User>(model)); 
     if (!createResult.Succeeded) 
     { 
      // handle failure.. 
     }     
    } 

    return await SignInWithFacebook(model.Email); 
} 

類的去連載從Facebook的圖形REST服務響應

public class FacebookAgeRange 
{ 
    public int Min { get; set; } 
} 

public class FacebookMeResponse 
{ 
    public string Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Email { get; set; } 
    public string Gender { get; set; } 
    public FacebookAgeRange AgeRange { get; set; } 
    public string PublicProfilePhotoUrl { get; set; } 
} 

public class FacebookResponse : IResponse 
{ 
    public bool Ok { get; set; } 
    public string Message { get; set; } 
    public string JwtToken { get; set; } 

    public FacebookResponse(string message, bool ok = true, string jwtToken = "") 
    { 
     this.Message = message; 
     this.Ok = ok; 
     this.JwtToken = jwtToken; 
    } 
}