You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by George Christman <gc...@cardaddy.com> on 2012/07/29 03:12:20 UTC

Tapestry Security Federate Facebook Exception

Hello, I'm trying to authenticate with a third party using Tapestry Security
Federate. 

I'm receiving the following error, however I don't know how to correct it. 

facebook account
error A Facebook federated user cannot be signed in, report this to support.
No account information found for authentication token
[AAAAADYIf8mQBAGaZCOiMQGStmQR6uOcjPuHcoTsRWb2jkERdKXZCZACsuCWaA08drmNnCAKZCrYJom8H6Ra0cpksVgCYbE8jfJkk8ZBKNVQZDZD]
by this Authenticator instance. Please check that it is configured
correctly. 



--
View this message in context: http://tapestry.1045711.n5.nabble.com/Tapestry-Security-Federate-Facebook-Exception-tp5714861.html
Sent from the Tapestry - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Tapestry Security Federate Facebook Exception

Posted by George Christman <gc...@cardaddy.com>.
Hi Kalle, 

The link you provided me doesn't seem to be working. I was able to get it to
work using your FederatedAccountServiceExample.class, however I have some
additional questions. 

I'd like to start by explaining my goals. I'd like to use a native login
with the option to use a third party login such as facebook. I'm using
hibernate and would need to be able to sync the database up with the third
party. 

1.) I'm assuming UserRealm is for native logins and not used by the third
party?
2.) Not sure why, but I was unable to get things working with
DefaultHibernateFederatedAccountService.class, I was getting the previously
posted error. 
3.) If I was able to get the DefaultHibernateFederatedAccountService.class
working, would I be able to sync and update the database?
4.) When clicking the facebook login link, for a fraction of a second the
redirect screen appears. Is there a way to prevent that from happening? I
notice it happens in your demo as well. 
5.) I don't know how to use Federated in the BasicUser.class hibernate
persistence class. My persistance class, "BasicUser" models your example
with the exception of roles,
http://svn.codehaus.org/tynamo/trunk/tynamo-federatedaccounts/tynamo-federatedaccounts-core/src/test/java/org/tynamo/security/federatedaccounts/testapp/entities/User.java

Below is my implementation, "I'm not really sure how to best merge the
database with the remote user", but hopefully you'll be able to point me in
the right direction. Any help would be appreciated. Thanks Kalle

@SubModule(value = {SecurityModule.class, FederatedAccountsModule.class})
public class AppModule {

    public static void bind(ServiceBinder binder) {
        binder.bind(UserInfo.class, UserInfoImpl.class);

        binder.bind(AuthorizingRealm.class,
FederatedAccountsAuthorizingRealm.class).withId(
                FederatedAccountsAuthorizingRealm.class.getSimpleName());
        binder.bind(FederatedAccountService.class,
FederatedAccountServiceExample.class);

    }

    @Startup
    public static void initApplication(Scheduler scheduler) {
        scheduler.init();
    }

    public static void
contributeFederatedAccountService(MappedConfiguration<String, Object>
configuration) {
        configuration.add("facebook", BasicUser.class);
        configuration.add("facebook.id", "facebookEmail");
//        configuration.add("twitter.id", "twitterUserId");
    }

    public static void contributeApplicationDefaults(
            MappedConfiguration<String, String> configuration) {
        // Contributions to ApplicationDefaults will override any
contributions to
        // FactoryDefaults (with the same key). Here we're restricting the
supported
        // locales to just "en" (English). As you add localised message
catalogs and other assets,
        // you can extend this list of locales (it's a comma separated
series of locale names;
        // the first locale name is the default when there's no reasonable
match).

        configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");

        // The factory default is true but during the early stages of an
application
        // overriding to false is a good idea. In addition, this is often
overridden
        // on the command line as -Dtapestry.production-mode=false
        configuration.add(SymbolConstants.PRODUCTION_MODE, "false");

        // The application version number is incorprated into URLs for some
        // assets. Web browsers will cache assets because of the far future
expires
        // header. If existing assets are changed, the version number should
also
        // change, to force the browser to download new versions.
        configuration.add(SymbolConstants.APPLICATION_VERSION,
"1.0-SNAPSHOT");

        configuration.add(JQuerySymbolConstants.SUPPRESS_PROTOTYPE, "true");
        configuration.add(FacebookRealm.FACEBOOK_CLIENTID, "Util.clientID");
        configuration.add(FacebookRealm.FACEBOOK_CLIENTSECRET,
"Util.clientSecret");
        configuration.add(FacebookRealm.FACEBOOK_PERMISSIONS,
"email,user_birthday,user_location");
        configuration.add(FacebookRealm.FACEBOOK_PRINCIPAL,
FacebookRealm.PrincipalProperty.email.name());

        configuration.add(SecuritySymbols.LOGIN_URL, "/login");

        configuration.add(SymbolConstants.HOSTNAME, "localhost");
        configuration.add(SymbolConstants.HOSTPORT, "8080");
        configuration.add(FederatedAccountSymbols.SUCCESSURL,
"/community/index");

    }

    public static void contributeWebSecurityManager(Configuration<Realm>
configuration, @InjectService("UserRealm") AuthorizingRealm userRealm) {
        // FacebookRealm is automatically contributed as long as
federatedsecurity is on the classpath
        configuration.add(userRealm);
    }

    public static void
contributeHibernateSessionSource(OrderedConfiguration<HibernateConfigurer>
configuration) {
        configuration.addInstance("cardaddy",
CarDaddyHibernateConfigurer.class);
    }

    @Match("*DAO")
    public static void adviseTransactions(HibernateTransactionAdvisor
advisor, MethodAdviceReceiver receiver) {
        advisor.addTransactionCommitAdvice(receiver);
    }






public class FederatedAccountServiceExample implements
FederatedAccountService {

    @Inject
    private Session session;
            
    @Inject
    private ApplicationStateManager applicationStateManager;

    @Override
    public AuthenticationInfo federate(String realmName, Object
remotePrincipal, AuthenticationToken authenticationToken, Object
remoteAccount) {
        BasicUser user = this.merge(remoteAccount);
        SimplePrincipalCollection principalCollection = new
SimplePrincipalCollection(remotePrincipal, realmName);
        principalCollection.add(authenticationToken, realmName);
        user.federate(realmName, remotePrincipal, remoteAccount);
        return new SimpleAuthenticationInfo(user.getId(),
authenticationToken.getCredentials(), realmName);
    }

    public BasicUser merge(com.restfb.types.User user) {
        BasicUser basicUser = (BasicUser)
session.createCriteria(BasicUser.class).add(Restrictions.eq("facebookUserId",
user.getId())).uniqueResult();

        if (basicUser == null) {
            basicUser = new BasicUser();
        }

        basicUser.setFirstName(user.getFirstName());
        basicUser.setLastName(user.getLastName());
        basicUser.setEmailAddress(user.getEmail());
        basicUser.setFacebookUserId(user.getId());
        session.saveOrUpdate(basicUser);
        return basicUser;
    }

    public BasicUser merge(Object account) {
        if (account instanceof com.restfb.types.User) {
            return merge((com.restfb.types.User) account);
        } else if (account instanceof twitter4j.User) {
            return merge((twitter4j.User) account);
        }
        return null;
    }
}







public class FederatedAccountsAuthorizingRealm extends AuthorizingRealm {

    private Logger logger;

    public FederatedAccountsAuthorizingRealm(Logger logger) {
        super(new MemoryConstrainedCacheManager());
        this.logger = logger;
        setName("oauthauthorizer");
        setAuthenticationTokenClass(OauthAccessToken.class);
        setPermissionResolver(new WildcardPermissionResolver());
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
principals) {
        // We are overcomplicating things for the purposes of this example
        // If you really only wanted to know if user was authenticated
against Facebook or Twitter,
        // you do the above check in any page or service by obtaining
Subject from SecurityService
        // However, we wanted to demonstrate local authorization with remote
authentication
        SimpleAuthorizationInfo authorizationInfo = new
SimpleAuthorizationInfo();
        if
(!principals.fromRealm(FederatedAccount.FederatedAccountType.facebook.name()).isEmpty())
{
           
authorizationInfo.addStringPermission(FederatedAccount.FederatedAccountType.facebook.name());
        }
        // Might be odd if these were both true at the same time but we
don't care
        if
(!principals.fromRealm(FederatedAccount.FederatedAccountType.twitter.name()).isEmpty())
{
           
authorizationInfo.addStringPermission(FederatedAccount.FederatedAccountType.twitter.name());
        }
        if (!principals.fromRealm("local").isEmpty()) {
            authorizationInfo.addStringPermission("local");
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken
token) throws AuthenticationException {
        // Never participate in authentication process
        return null;
    }
}




@Scope(ScopeConstants.PERTHREAD)
public class UserInfoImpl implements UserInfo {

    private final Session session;

    public UserInfoImpl(Session session) {
        this.session = session;
    }

    public Long getUserId() {
        return (Long) SecurityUtils.getSubject().getPrincipal();
    }

    public BasicUser getUser() {
        Long userId = getUserId();

        if (userId != null) {
            return (BasicUser) session.get(BasicUser.class, userId);
        }

        return null;
    }

}




@Entity
public class BasicUser implements FederatedAccount, Serializable {

    private Long id;
    private String facebookUserId;
    private String username;
    private String firstName;
    private String lastName;
    private String emailAddress;
    private String encodedPassword;
    private Date created = new Date();
    private boolean accountLocked;
    private boolean credentialsExpired;
    private byte[] passwordSalt;
    private List<Vehicle> vehicles;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @NonVisual
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        try {
            return (obj instanceof BasicUser && ((BasicUser)
obj).getUsername().equals(username));
        } catch (NullPointerException e) {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return username == null ? 0 : username.hashCode();
    }

    @OneToMany(mappedBy = "basicUser", cascade = CascadeType.ALL)
    public List<Vehicle> getVehicles() {
        return vehicles;
    }

    public void setVehicles(List<Vehicle> vehicles) {
        this.vehicles = vehicles;
    }

    @NaturalId
    @Column(unique = true)
    @Index(name = "User_username")
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

   
@Validate("required,regexp=^[0-9a-zA-Z._%+-]+@[0-9a-zA-Z]+[\\.]{1}[0-9a-zA-Z]+[\\.]?[0-9a-zA-Z]+$")
    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    @NonVisual
    public String getEncodedPassword() {
        return encodedPassword;
    }

    public void setEncodedPassword(String encodedPassword) {
        this.encodedPassword = encodedPassword;
    }

    @NonVisual
    @Temporal(javax.persistence.TemporalType.DATE)
    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public boolean isAccountLocked() {
        return accountLocked;
    }

    public void setAccountLocked(boolean accountLocked) {
        this.accountLocked = accountLocked;
    }

    public boolean isCredentialsExpired() {
        return credentialsExpired;
    }

    public void setCredentialsExpired(boolean credentialsExpired) {
        this.credentialsExpired = credentialsExpired;
    }

    @Transient
    public String getPassword() {
        return "";
    }

    public void setPassword(String password) {
        if (password != null && !password.equals(encodedPassword) &&
!"".equals(password)) {
            ByteSource saltSource = new
SecureRandomNumberGenerator().nextBytes();
            this.passwordSalt = saltSource.getBytes();
            this.encodedPassword = new Sha1Hash(password,
saltSource).toString();
        }
    }

    @Override
    public String toString() {
        return "User " + username;
    }

    public void setFacebookUserId(String facebookUserId) {
        this.facebookUserId = facebookUserId;
    }

    @NonVisual
    @Column(unique = true, nullable = true)
    public String getFacebookUserId() {
        return facebookUserId;
    }

    public void setPasswordSalt(byte[] passwordSalt) {
        this.passwordSalt = passwordSalt;
    }

    @NonVisual
    @Column(length = 128)
    public byte[] getPasswordSalt() {
        return passwordSalt;
    }

    @Override
    public boolean federate(String realmName, Object remotePrincipal, Object
remoteAccount) {
        if (remoteAccount instanceof com.restfb.types.User) {
            // remotePrincipal is null, this is a federated account update
            if (remotePrincipal == null) {
                // update federated/overlapping properties
            } else {
                // newly created account but oviously you could also check
if (local) id is null
                // If you don't allow auto-federation and didn't implement a
custom FederatedAccountService,
                // you could throw an exception here or initialize the
account in locked state
                com.restfb.types.User fbUser = (com.restfb.types.User)
remoteAccount;
                facebookUserId = fbUser.getId();
                // initialize other federated/overlapping properties
            }
        }
        return false;
    }
}














--
View this message in context: http://tapestry.1045711.n5.nabble.com/Tapestry-Security-Federate-Facebook-Exception-tp5714861p5714863.html
Sent from the Tapestry - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Tapestry Security Federate Facebook Exception

Posted by Kalle Korhonen <ka...@gmail.com>.
Well, you have to debug your federatedaccount service implementation,
just put a breakpoint on the federate() call and see what you get. If
you are using the built-in implementation classes, the typical issue
to trip over is that you haven't configured or you've incorrectly
configured the associated principal (see and understand contributions
to federated account service:
http://tynamo.org/tynamo-federatedaccounts+guide).

Kalle


On Sat, Jul 28, 2012 at 6:12 PM, George Christman
<gc...@cardaddy.com> wrote:
> Hello, I'm trying to authenticate with a third party using Tapestry Security
> Federate.
>
> I'm receiving the following error, however I don't know how to correct it.
>
> facebook account
> error A Facebook federated user cannot be signed in, report this to support.
> No account information found for authentication token
> [AAAAADYIf8mQBAGaZCOiMQGStmQR6uOcjPuHcoTsRWb2jkERdKXZCZACsuCWaA08drmNnCAKZCrYJom8H6Ra0cpksVgCYbE8jfJkk8ZBKNVQZDZD]
> by this Authenticator instance. Please check that it is configured
> correctly.
>
>
>
> --
> View this message in context: http://tapestry.1045711.n5.nabble.com/Tapestry-Security-Federate-Facebook-Exception-tp5714861.html
> Sent from the Tapestry - User mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org