GithubHelp home page GithubHelp logo

Comments (13)

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

@clone1985 thanks for pointing out this issue. I pushed a new version of the library: https://www.nuget.org/packages/AspNet.Identity.RavenDB/2.0.0-pre-06 can you try with the new version and see if the issue continues. It should be solved.

The reason why I don't prefer to implement FindAsync as you did is to avoid unnecessary index creation. In my implementation, I'm doing two queries but all are performed on the document Id.

from aspnet.identity.ravendb.

MortenChristiansen avatar MortenChristiansen commented on August 10, 2024

Thanks, that did the trick.

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

Nice! Thanks for confirming!

from aspnet.identity.ravendb.

MortenChristiansen avatar MortenChristiansen commented on August 10, 2024

It appears I was too quick to close the issue. It suddenly stopped working again without me having done anything to provoke it, so I think I was still running with my modified version cached for a while.

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

Can you provide the error message that you get or repro steps so that I can reproduce the exact same problem?

from aspnet.identity.ravendb.

MortenChristiansen avatar MortenChristiansen commented on August 10, 2024

The RavenDB log says:

Document with key 'RavenUserLogins/Google/https://www.google.com/accounts/o8/id?id=MYKEY' was not found

This makes sense to me (and my limited understanding of RavenDB) since there is no document with an id like that (see the original bug description). Note that the id it searches for matches the one in the Logins collection ('Id') perfectly, so that is not the problem. So my original conclusion still stands that the way you look for the login does not work as intended.

I created a repro project that is the default VS 2013 SPA template where I just replaced the persistence to use the newest AspNet.Identity.RavenDB package. You just need to enter a valid connection string in the web.config and try to register a Google account. After registering it you should see the same log in the RavenDB Studio that the document could not be found.
https://onedrive.live.com/redir?resid=48F0E076F4DD5267!19633&authkey=!ALSCar9Ktmtu1NI&ithint=file%2c.zip

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

@clone1985 thanks, looking into it now.

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

@clone1985 I figured out the problem.

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

    Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);

    AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);

    if (ticket == null || ticket.Identity == null || (ticket.Properties != null
        && ticket.Properties.ExpiresUtc.HasValue
        && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
    {
        return BadRequest("External login failure.");
    }

    ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);

    if (externalData == null)
    {
        return BadRequest("The external login is already associated with an account.");
    }

    IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
        new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));

    IHttpActionResult errorResult = GetErrorResult(result);

    if (errorResult != null)
    {
        return errorResult;
    }

    return Ok();
}

Inside this method, UserManager.AddLoginAsync is called and UserManager.UpdateAsync is not called. RavenUserStore does not save changes on every call. It only does it with UpdateAsync method.

On the other hand, I would suggest to work with the UoW pattern as Ayende described here: http://ayende.com/blog/163170/building-async-unit-of-work-with-mvc-4 By going with this option, you shouldn't make any configuration changes to the AccountController class which comes with the project templates.

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

I'm going to write a blog post about how to make RavenDB port of ASP.NET identity work with the default templates soon.

from aspnet.identity.ravendb.

MortenChristiansen avatar MortenChristiansen commented on August 10, 2024

I'm afraid that is not the problem I have, since I do not use the AddExternalLogin method at all (though it is nice to know since I will likely be using it in the future). If there should be a problem with my code, it would likely be in RegisterExternal or GetExternalLogin.

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

I see your problem now:

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

        ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

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

        RavenUser user = new RavenUser(model.UserName);
        user.AddLogin(new RavenUserLogin(externalLogin.UserName, new UserLoginInfo(externalLogin.LoginProvider, externalLogin.ProviderKey)));
        IdentityResult result = await UserManager.CreateAsync(user);
        IHttpActionResult errorResult = GetErrorResult(result);

        if (errorResult != null)
        {
            return errorResult;
        }

        return Ok();
    }

Why are you calling user.AddLogin there? You should call UserManager.AddLoginAsync instead right after you call UserManager.CreateUserAync (just like I did here: 2dc4108).

Here is the correctly implemented version of that method:

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

    ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

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

    RavenUser user = new RavenUser(model.UserName);
    IdentityResult result = await UserManager.CreateAsync(user);
    if (result.Succeeded)
    {
        result = await UserManager.AddLoginAsync(user.Id, new UserLoginInfo(externalLogin.LoginProvider, externalLogin.ProviderKey));
        if (result.Succeeded)
        {
            return Ok();
        }
    }

    return GetErrorResult(result);
}

from aspnet.identity.ravendb.

MortenChristiansen avatar MortenChristiansen commented on August 10, 2024

Yes, that works. The reason I did it that way is due to the original code which was defined like this:

...
IdentityUser user = new IdentityUser
{
    UserName = model.UserName
};
user.Logins.Add(new IdentityUserLogin
{
    LoginProvider = externalLogin.LoginProvider,
    ProviderKey = externalLogin.ProviderKey
});
IdentityResult result = await UserManager.CreateAsync(user);
...

It only seemed natural to continue the same pattern. If you write up a blog post about it make sure to point this out. While it turned out that there was no bug after all, I think it served to highlight that a bit of guidance would be helpful.

Thanks for looking into my problems :)

from aspnet.identity.ravendb.

tugberkugurlu avatar tugberkugurlu commented on August 10, 2024

Thanks for that code snippet.

That's the wrong way of doing it. I filed an issue on ASP.NET Identity repository: https://aspnetidentity.codeplex.com/workitem/2165 You can vote it up.

from aspnet.identity.ravendb.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.