Giter Club home page Giter Club logo

Comments (3)

tazmaniax avatar tazmaniax commented on July 21, 2024

Hi Jorge,

In the end I modified IdentifyProvider.authenticate() and made it backwards compatible. I followed the same example in the OAuth1 redirect by putting the user in the cache then redirecting to another action if one is defined in config and if necessary (e.g. email is not defined), with the cache key and return URL as parameters. The external action retrieves and updates the cached user as necessary and then redirects back to the authenticated method. On re-entry to the authentication method the cached user is checked for existence, then the cache is cleared and the updated cached user is set to be the one that will be saved. Is this a reasonable solution? Tempted to put the original URL in the cache to avoid any reliance on the external action having to preserve it.

As a general point, I'm guessing that for a clustered environment a clustered cache like memcached is required to ensure the cached SocialUser instance is accessible from all machines. This isn't mentioned in the documentation and only by looking at the code dependence on the cache would this be obvious. yes?

   protected IdentityProvider(ProviderType type, AuthenticationMethod authMethod) {
        this.type = type;
        this.authMethod = authMethod;
        this.action = Play.configuration.getProperty(getPropertiesKey(this.type) + "action");
    }

   public SocialUser authenticate() {
        SocialUser user = null;

        final String key = (this.action != null) ? new StringBuilder(SECURESOCIAL).append("ext.").append(Scope.Session.current().getId()).toString() : null;
        SocialUser externalUser = (key != null) ? (SocialUser) Cache.get(key) : null;

        if (externalUser == null) {     
            // authenticate against the 3rd party service (facebook, twitter, etc)
            Map<String, Object> authContext = new HashMap<String, Object>();
            user = doAuth(authContext);

            // if user authenticated correctly, retrieve some profile information
            fillProfile(user, authContext);

            if (this.action != null && user.email == null) {
                // Check if there is an existing user and if it has the email set.
                SocialUser existingUser = UserService.find(user.id);
                if (existingUser == null || existingUser.email == null) {
                    Cache.safeSet(key, user, "10min");
                    Flash.current().keep(SecureSocial.ORIGINAL_URL);
                    Map<String, Object> args = new HashMap<String, Object>();
                    args.put("returnURL", Request.current().getBase() + Request.current().path);
                    args.put("key", key);
                    throw new Redirect(Router.getFullUrl(this.action, args));
                }

                user.email = existingUser.email;
            }
        } else {
            Cache.delete(key);
            user = externalUser;
        }

        // save the user
        user.lastAccess = new Date();
        UserService.save(user);

        // we're done.
        return user;
    }

cheers,
Chris

from securesocial.

jaliss avatar jaliss commented on July 21, 2024

Hi Chris,

I completely forgot to reply this. I'm sorry. That approach works, another thing you could have done is check if the user has an email within your application flow (after authentication) using a @before interceptor and if missing redirect the user to a page where he can complete his profile. After that he would be redirected again to the original destination page.

And you're right about the cache. In a clustered environment you'd need something like memcached.

Jorge

from securesocial.

jaliss avatar jaliss commented on July 21, 2024

@tazmaniax I'm closing this, hope my comments above helped.

from securesocial.

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.