加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – MVC 5 Web API与Facebook访问令牌到RegisterExternal而不需要Coo

发布时间:2020-05-28 21:52:33 所属栏目:asp.Net 来源:互联网
导读:建立: 新的MVC5项目只用Web API.添加了Facebook AppId和Secret. 通过传入UserName和Password,我可以从Token端点获取我的Web API的Token.然后使用该令牌进行进一步的呼叫. 但 我想在iOS应用程序的Facebook SDK的帮助下注册新用户. 我正在使用Facebook SDK获取

建立:
新的MVC5项目只用Web API.添加了Facebook AppId和Secret.

通过传入UserName和Password,我可以从Token端点获取我的Web API的Token.然后使用该令牌进行进一步的呼叫.

我想在iOS应用程序的Facebook SDK的帮助下注册新用户.
我正在使用Facebook SDK获取访问令牌. (假设在这一点上,我有一个访问令牌).

接下来我知道的是通过将该令牌传递给具有承载[访问令牌]的授权头部,但是会导致500个服务器错误,从而调用api / Account / RegisterExternal端点.

我想我知道的原因,Cookie缺失.我用Fidler的一个cookie做了同样的电话,它的工作. (通过转到ExternalLogins端点提供的URL接收Cookie).
由于cookie缺少等待Authentication.GetExternalLoginInfoAsync();在RegisterExternal操作内返回null.

// POST api/Account/RegisterExternal
        [OverrideAuthentication]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("RegisterExternal")]
        public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

        var info = await Authentication.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return InternalServerError();
        }

        var user = new ApplicationUser() { UserName = model.Email,Email = model.Email };

        IdentityResult result = await UserManager.CreateAsync(user);
        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        result = await UserManager.AddLoginAsync(user.Id,info.Login);
        if (!result.Succeeded)
        {
            return GetErrorResult(result); 
        }
        return Ok();
    }

我不想对我的Web API进行3次调用,要求外部登录,然后转到该URL并在Web浏览器中进行身份验证,以访问Facebook访问令牌,然后使用我需要收集的访问令牌和Cookie调用RegisterExternal端点在这些电话之间.

正如我所说,除了Facebook Ids,我没有改变任何模板.仍然代码如下.

public partial class Startup
    {
        public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

        public static string PublicClientId { get; private set; }

        // For more information on configuring authentication,please visit http://go.microsoft.com/fwlink/?LinkId=301864
        public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context and user manager to use a single instance per request
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            // Enable the application to use a cookie to store information for the signed in user
            // and to use a cookie to temporarily store information about a user logging in with a third party login provider
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);



            // Configure the application for OAuth based flow
            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),Provider = new ApplicationOAuthProvider(PublicClientId),AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),AllowInsecureHttp = true
            };

            // Enable the application to use bearer tokens to authenticate users
            app.USEOAuthBearerTokens(OAuthOptions);


            app.UseFacebookAuthentication(
              appId: "xxxxxxxxxxxxxxx",appSecret: "xxxxxxxxxxxxxxxxxxxxxxxx");

        }
    }

据我所知,Web API不需要Cookie,当我从令牌端点获得本地令牌,但为什么在执行ExternalRegister时首先需要Cookie
WebApiConfig类看起来像这样,不应该config.SuppressDefaultHostAuthentication();避免任何Cookie的需求

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",routeTemplate: "api/{controller}/{id}",defaults: new { id = RouteParameter.Optional }
            );
        }
    }

我不知道我是否在这里错过了这一点.我的意图是不需要在本机iOS应用程序中使用Web浏览器进行令牌.那就是Facebook SDK获取访问令牌,并使用该调用RegisterExternal获取本地令牌并创建该用户身份.

我做了我的功课,我坚持这个想法.
思想赞赏!

解决方法

我误以为它接受了Cookie的社交令牌!
它不直接接受任何外部令牌.

事情是.. MVC 5正在为我们照顾一切,即从社会媒体收集令牌并验证/处理它.之后,它生成一个本地令牌.

RegisterExternal方法还需要维护Cookie,解决方案不会.

我写了一个blog post,这将详细解释.在下面添加了直接的答案.我的目标是使其融合并成为默认MVC Web API的登录/注册流程的组成部分,以确保其易于理解.

在下面的解决方案之后,授权属性必须如下才能工作,否则您将获得未经授权的响应.

[Authorize]
[HostAuthentication(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalBearer)]
[HostAuthentication(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie)]

如果要仅允许令牌使用API,请使用ExternalBearer,如果要仅允许记录的Cookie使用API即从网站使用ApplicationCookie.如果您要允许两者的API,用户都可以.

将此操作添加到AccountController.cs

// POST api/Account/RegisterExternalToken
[OverrideAuthentication]
[AllowAnonymous]
[Route("RegisterExternalToken")]
public async Task<IHttpActionResult> RegisterExternalToken(RegisterExternalTokenBindingModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    ExternalLoginData externalLogin = await ExternalLoginData.FromToken(model.Provider,model.Token);



    if (externalLogin == null)
    {
        return InternalServerError();
    }

    if (externalLogin.LoginProvider != model.Provider)
    {
        Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        return InternalServerError();
    }

    ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,externalLogin.ProviderKey));

    bool hasRegistered = user != null;
    ClaimsIdentity identity = null;
    IdentityResult result;

    if (hasRegistered)
    {
        identity = await UserManager.CreateIdentityAsync(user,OAuthDefaults.AuthenticationType);
        IEnumerable<Claim> claims = externalLogin.GetClaims();
        identity.AddClaims(claims);
        Authentication.SignIn(identity);
    }
    else
    {
        user = new ApplicationUser() { Id = Guid.NewGuid().ToString(),UserName = model.Email,Email = model.Email };

        result = await UserManager.CreateAsync(user);
        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        var info = new ExternalLoginInfo()
        {
            DefaultUserName = model.Email,Login = new UserLoginInfo(model.Provider,externalLogin.ProviderKey)
        };

        result = await UserManager.AddLoginAsync(user.Id,info.Login);
        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        identity = await UserManager.CreateIdentityAsync(user,OAuthDefaults.AuthenticationType);
        IEnumerable<Claim> claims = externalLogin.GetClaims();
        identity.AddClaims(claims);
        Authentication.SignIn(identity);
    }

    AuthenticationTicket ticket = new AuthenticationTicket(identity,new AuthenticationProperties());
    var currentUtc = new Microsoft.Owin.Infrastructure.SystemClock().UtcNow;
    ticket.Properties.IssuedUtc = currentUtc;
    ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromDays(365));
    var accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
    Request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer",accessToken);



    // Create the response building a JSON object that mimics exactly the one issued by the default /Token endpoint
    JObject token = new JObject(
        new JProperty("userName",user.UserName),new JProperty("id",user.Id),new JProperty("access_token",accessToken),new JProperty("token_type","bearer"),new JProperty("expires_in",TimeSpan.FromDays(365).TotalSeconds.ToString()),new JProperty(".issued",currentUtc.ToString("ddd,dd MMM yyyy HH':'mm':'ss 'GMT'")),new JProperty(".expires",currentUtc.Add(TimeSpan.FromDays(365)).ToString("ddd,dd MMM yyyy HH:mm:ss 'GMT'"))
    );
    return Ok(token);
}

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读