So I set org.apache.shiro to DEBUG level and discovered that Shiro is actually correctly authenticating but for some reason displays "Unauthorized" page:
[DEBUG] com.foo.bar.core.engine.components.dao.UserManagementMockDao (getUser:444) - userId: donkey [DEBUG] com.foo.bar.core.engine.components.dao.UserManagementMockDao (getUserPassword:451) - userId: donkey [DEBUG] org.apache.shiro.realm.AuthenticatingRealm (getAuthenticationInfo:569) - Looked up AuthenticationInfo [donkey] from doGetAuthenticationInfo [DEBUG] org.apache.shiro.realm.AuthenticatingRealm (cacheAuthenticationInfoIfPossible:507) - AuthenticationInfo caching is disabled for info [donkey]. Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - donkey, rememberMe=false]. [DEBUG] org.apache.shiro.authc.credential.SimpleCredentialsMatcher (equals:95) - Performing credentials equality check for tokenCredentials of type [[C and accountCredentials of type [java.lang.String] [DEBUG] org.apache.shiro.authc.credential.SimpleCredentialsMatcher (equals:101) - Both credentials arguments can be easily converted to byte arrays. Performing array equals comparison [DEBUG] org.apache.shiro.authc.AbstractAuthenticator (authenticate:233) - Authentication successful for token [org.apache.shiro.authc.UsernamePasswordToken - donkey, rememberMe=false]. Returned account [donkey] [DEBUG] org.apache.shiro.subject.support.DefaultSubjectContext (resolveSecurityManager:102) - No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup. [DEBUG] org.apache.shiro.subject.support.DefaultSubjectContext (resolveSecurityManager:102) - No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup. [DEBUG] org.apache.shiro.web.servlet.SimpleCookie (addCookieHeader:226) - Added HttpServletResponse Cookie [rememberMe=deleteMe; Path=/bip; Max-Age=0; Expires=Tue, 08-Nov-2016 12:28:52 GMT] [DEBUG] org.apache.shiro.mgt.AbstractRememberMeManager (onSuccessfulLogin:290) - AuthenticationToken did not indicate RememberMe is requested. RememberMe functionality will not be executed for corresponding account. [DEBUG] org.apache.shiro.realm.AuthorizingRealm (getAuthorizationCacheLazy:234) - No authorizationCache instance set. Checking for a cacheManager... [DEBUG] org.apache.shiro.realm.AuthorizingRealm (getAuthorizationCacheLazy:242) - CacheManager [MemoryConstrainedCacheManager with 0 cache(s)): []] has been configured. Building authorization cache named [awsiamaccounts.authorizationCache] So I must have a misconfiguration somewhere but am stuck as I can't figure out where. I just thought that tapestry-security automagically handles redirect after login. My page is very simple: @RequiresRoles("administrator") public class Contact { } On Tue, Nov 8, 2016 at 8:30 PM, Adam X <vbgnm3c...@gmail.com> wrote: > Hi Kyle, > > Thanks for taking a look. Indeed, I made the assumption that > SimpleCredentialsMatcher is used by default, but as part of my > troubleshooting I explicitly set it. doGetAuthenticationInfo is > invoked for sure, because my logs show it (I also stepped thru with > the debugger): > > [WARN] org.tynamo.security.services.SecurityModule.RememberMeManager > (buildRememberMeManager:111) - Symbol 'security.remembermecipherkey' > is not set, using 'tapestry.hmac-passphrase' as the cipher. Beware > that changing the value will invalidate rememberMe cookies > [ERROR] org.apache.tapestry5.modules.AssetsModule.AssetSource > (invoke:237) - Packaging of classpath assets has changed in release > 5.4; Assets should no longer be on the main classpath, but should be > moved to 'META-INF/assets/' or a sub-folder. Future releases of > Tapestry may no longer support assets on the main classpath. > [WARN] org.apache.tapestry5.modules.AssetsModule.AssetSource > (invoke:245) - Classpath asset '/org/tynamo/security/img/login-bg.png' > should be moved to folder > '/META-INF/assets/security/org/tynamo/security/img/'. > [DEBUG] com.foo.bar.core.engine.components.dao.UserManagementMockDao > (getUser:444) - userId: donkey > [DEBUG] com.foo.bar.core.engine.components.dao.UserManagementMockDao > (getUserPassword:451) - userId: donkey > > As you can see my mock dao is correctly being called and it is > returning the correct password because I saw it in the debugger. > > Am I instantiating SimpleAuthenticationInfo correctly? This API is all > new to me (never worked with Shiro) so I'm learning as I go. > > Also, here is what my AppModule contribution looks like: > > @Contribute(WebSecurityManager.class) > public static void addRealms(Configuration<Realm> configuration, > @Inject @FromFactory UserManagementDao dao) { > Realm realm = new FooBarCoreRealm(dao); > configuration.add(realm); > } > > Obviously replaced company name with FooBar etc. > > Adam > > On Tue, Nov 8, 2016 at 7:55 PM, Kalle Korhonen > <kalle.o.korho...@gmail.com> wrote: >> Looks fine at a quick glance. As I recall, an AuthenticatingRealm uses >> SimpleCredentialsMatcher by so it should match plain text passwords. Are >> you sure it's not authenticating, or is doGetAuthenticationInfo invoked at >> all? Do you have any other realms configured? Get the simple, single realm >> use case working first and work from there. >> >> Kalle >> >> On Tue, Nov 8, 2016 at 10:16 AM, Adam X <vbgnm3c...@gmail.com> wrote: >> >>> Howdy ! >>> >>> I followed tynamo setup guide >>> (http://www.tynamo.org/tapestry-security+guide/) combined with >>> federated accounts example >>> (https://github.com/tynamo/tynamo-federatedaccounts). I believe I have >>> the setup hooked up correctly as my annotated page with >>> @RequiresRoles("administrator") is not intercepted by tynamo and a >>> login page appears. The problem I'm having is that when I enter valid >>> credentials tynamo is not authenticating. Below is my custom realm. >>> UserManagementDao is just an interface, but the implementation I'm >>> injecting is a simple in-memory hash map impl with a unit test >>> verifyinig it's correctness (in reality we're authenticating against >>> AWS IAM but I'm usinig mock to get things working initially). However, >>> I'm not sure if I'm constructing SimpleAuthenticationInfo correctly. >>> Another thing is that my passwords (for now) are clear text and I'm >>> not sure if by default Tynamo uses clear text comparison of if it >>> hashes the passwords. >>> >>> Any help would be highly appreciated! >>> >>> public class MyCustomRealm extends AuthorizingRealm { >>> >>> private UserManagementDao dao; >>> >>> >>> public XappmCoreRealm(UserManagementDao dao) { >>> >>> super(new MemoryConstrainedCacheManager()); >>> setName("awsiamaccounts"); >>> setAuthenticationTokenClass(UsernamePasswordToken.class); >>> //setCredentialsMatcher(new >>> HashedCredentialsMatcher(Sha1Hash.ALGORITHM_NAME)); >>> >>> this.dao = dao; >>> } >>> >>> @Override >>> protected AuthorizationInfo >>> doGetAuthorizationInfo(PrincipalCollection principals) { >>> >>> if(principals == null) throw new >>> AuthorizationException(String.format("null %s! (should not happen)", >>> PrincipalCollection.class.getSimpleName())); >>> if(principals.isEmpty()) return null; >>> if(principals.fromRealm(getName()).size() <= 0) return null; >>> >>> String username = (String) >>> principals.fromRealm(getName()).iterator().next(); >>> if(username == null) return null; >>> >>> List<XapGroup> groups = dao.getUserGroups(username); >>> Set<String> roles = new HashSet<>(); >>> >>> for(XapGroup group : groups) { >>> roles.add(group.getId()); >>> } >>> >>> return new SimpleAuthorizationInfo(roles); >>> } >>> >>> @Override >>> protected AuthenticationInfo >>> doGetAuthenticationInfo(AuthenticationToken token) throws >>> AuthenticationException { >>> >>> UsernamePasswordToken upToken = (UsernamePasswordToken) token; >>> String userName = upToken.getUsername(); >>> >>> if(userName == null) throw new AccountException("Null >>> usernames are not allowed by this realm."); >>> >>> XapUser user = dao.getUser(userName); >>> if(user == null) return null; >>> >>> // if (user.isAccountLocked()) { throw new >>> LockedAccountException("Account [" + username + "] is locked."); } >>> // if (user.isCredentialsExpired()) { >>> // String msg = "The credentials for account [" + username >>> + "] are expired"; >>> // throw new ExpiredCredentialsException(msg); >>> // } >>> >>> String password = dao.getUserPassword(userName); >>> >>> return new SimpleAuthenticationInfo(userName, password, >>> getName()); >>> } >>> } >>> >>> Adam >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >>> For additional commands, e-mail: users-h...@tapestry.apache.org >>> >>> --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org For additional commands, e-mail: users-h...@tapestry.apache.org