CBSecurity / CBAuth question -- we've got an app w...
# box-products
n
CBSecurity / CBAuth question -- we've got an app where if the user types in the wrong password, CBAuth is throwing an "InvalidCredentials" exception. However the cbSecurity module settings in ColdBox.cfc is looking for a setting called "invalidAuthenticationEvent"....which kind of implies the exception it's looking for is actually "InvalidAuthentication", not "InvalidCredentials". And since the exception types aren't the same, our "invalidAuthenticationEvent" ColdBox event never fires. This works:
Copy code
try
		{
			var userObj = AuthService.authenticate(username=rc.email, password=EncryptionService.hashPassword(rc.password));
		}
		catch( ex )
		{
			if( ex.type eq "InvalidCredentials" )
			{
				relocate( event="auth/onInvalidLogin", persistStruct={ errMsg: "something bad happened!" } );
			}
			
		}
...but that seems like the long way around the problem. Trying to figure out why our "invalidAuthenticationEvent' isn't firing off. Suggestions welcome. Thanks.
p
Hmm good question. Can you dump whatever the
ex
is outputting in your catch OR remove your If logic in your catch to see if it passes through and triggers the invalidAuthenticationEvent by default.
w
Hi Nolan, I think there is a not so obvious reason for that. cbsecurity has two security mechanisms, the handler/method annotations ( secured or secured-“somePermission” ) or permissions rules. In both cases your method or handler has to be protected so the invalidAuthentication or invalidAuthorization actions can be executed, which eventually lead to a relocate or override. I guess your
dologin
action has no cbsecurity protection (otherwise you can not even access it), and on executing your authenticate call the cbauth authenticationservice will call getUserService().isValidCredentials and if this is false it will throw the InvalidCredentials exception.
n
Why would a doLogin() method ever have cbsecurity protection? It's code that runs before someone is logged in? What am I missing here?
w
Tehnically the cbauth module knows nothing about the cbsecurity settings so your authentication server cannot even send it to our inValidAuthentication event. It shouldn’t be to difficult though to write your own authentication service which reads this cbsecurity settings and redirects/overwrites based on your preferences. But I guess it is a lot easier to just write one try / catch 🙂
no, I think we are misunderstanding
a doLogin doesn’t need cbsecurity protection. But that also means this doLogin doesn’t know anything about cbsecurity. It is simply ignored by cbsecurity because it does not match any rule
so although cbsecurity knows about cbauth, cbauth doesn’t now anything about cbsecurity.
First time I wrote a login method I had to really find out how this was working
n
I think we're talking about different things. I'm trying go log someone in. Not worried about secured pages yet....literally just trying to get the user to log in successfully, or throw the correct exception when they type in the wrong password. According to the cbSecurity docs, I should use the "invalidAuthenticationEvent" setting in ColdBox.cfc to specify my event. Currently I have that set to "auth.onInvalidLogin". ....but this event never runs. I've tried setting invalidAuthenticationEvent" to various things, none of them fire. It seems like that setting in cbSecurity doesn't actually do anything.
w
So what happens if your user is NOT logged in yet and you are trying to access a secured page? In that case you will get your invalidAuthenticationEvent
if you are logged in already but have unsufficient rights you will be directed to your invalidAuthorization event.
but in your login handler you are just talking to cbauth. No cbsecurity involved
It is just this authenticationService which is throwing this event. You could also implement it in a different way without this annoying InvalidCredentials exception
So let’s say you have an invalid authentication and you are not throwing an event but just returning without errors, your login event would just send you to the next page. In that case the next page will detect the invalid credentials and send you to the correct event. You could argue that this even makes more sense.
n
But I want the invalidCredentials thing to fire. The setting name is "invalidAuthenticationEvent"....which sounds like it should be running long before any "Authorization" things happen. I understand this is happening in cbAuth's AuthenticationService, not cbSecurity (though the setting "invalidAuthenticationEvent" is part of cbSecurity's stuff in ColdBox.cfc). Let me back up for a sec...when should the "invalidAuthenticationEvent" actually fire? To me, I think it should run when a user types in the wrong username/password on the "login" page....I'll have code there that calls authService.authenticate( username, password )....and according to the docs, if those credentials are wrong, it should throw an exception and run whatever ColdBox action I have defined in "invalidAuthenticationEvent". Is that correct?
w
Well, I don’t know what the docs say exactly, let me read it for a few seconds. But it certainly doesn’t fire the invalidAuthenticationEvent on invalid credentials. If the docs says so, they are wrong.
p
// The global invalid authentication event or URI or URL to go if an invalid authentication occurs
is what
invalidAuthenticationEvent
is commented. To me that means if you do NOT try to catch anything then it fires that event.
w
but that’s only true if your page is secured. that’s the whole point
p
Wouldnt the page not being secured fall under "invalidAuthorizationEvent" not "invalidAuthenticationEvent"
w
No! this whole page knows nothing about cbsecurity.\
It only asks credentials from an authentication service
if you would do a different authentication service which doesn’t throw errors, it would behave as you expected
that means: trying to authenticate, no matter what happens it sends you to the page you want after your login. And there it discovers there is no authenticated user and sends you to your InvalidAuthentication event.
so this InvalidCredentials exception is just a side effect of the cbauth module.
It is easy to test
n
but it's not actually sending anything to the "invalidAuthentication" event. That's my whole problem. 🙂 this setting appears to be ignored.
p
Nolan- I think you are all good, you can disregard that module setting "default" and utilize as you have in that working example.
n
I don't have a working example. 🙂
That's what I'm running now
p
You just showed code and titled it "This works"
n
"invalidAuthenticationEvent" never fires....no matter what ColdBox event I set it to.
w
The invalidAuthentication event only gets ignored on the login page. If you try to access any secured event it will definitely fire. Just try to go to a secured page and see where you are going.
n
Why would "invalidAuthentication" fire on any secured event? That's an authorization issue, not an authentication issue.
w
Nope, both. It is really buried in the code, but on processing the rules it is first checking if the user is logged in. If not it will do the InvalidAuthentication. If you continue but have invalid permissions it will fire the InvalidAuthorization.
I know, the manual is very very confusing. That’s why I wrote several blog posts on cbsecurity, but I guess this part had no focus on my blog 🙂
n
Okay so if I'm understanding you correctly, any machinery I want to write for handling "someone tried to use the wrong credentials" is up to me? And cbAuth doesn't actually provide code to help with that. Is that correct?
w
What datea are you looking for in the “someone tried to use the wrong credentials”?
If it just for catching invalid credentials, you could do what you suggested already. If you want to know more about the authentication there ’s more to discover
n
I was under the impression that cbAuth's AuthService.authenticate() would have settings so that "invalid login" also flows thru the cbAuth path the same way a "valid login" does. But it sounds like that's not the case.
w
It has this stupid exception. If you don’t want that, just change the code. One extra line and it works probably the way you want.
I didn’t invent this flow. It is not very intuitive and I think cbauth and cbsecurity should work together in a better way.
You should try this just for testing in the cbauth Authenticationservice
n
I've been using cbautho.authenticationservice this whole time. :) I agree, they should work together differently. It's weird that "invalid credentials" isn't handled the same way as other situations.
p
I have worked with Wil and asked lots of advice as he prob knows heh. But I would suggest giving a look at the ContentBox authentication setup and cut out a lot of the extras and should make sense. But your example code should do the trick.
n
Yeah my original code works...it just seemed like we're going about it the long way. I was expecting cbAuth to handle "invalid login" internally, without needing me to write try/catch blocks and handle it myself.
w
there’s a authenticate method which says:
Copy code
if ( !getUserService().isValidCredentials( arguments.username, arguments.password ) ) {
            variables.interceptorService.processState(
                "onInvalidCredentials",
                {
                    "username" : arguments.username,
                    "password" : arguments.password
                }
            );
            throw( type = "InvalidCredentials", message = "Incorrect Credentials Entered" );
        }
if you would prepend this with this line, I think you would have your desired workflow:
Copy code
if ( !getUserService().isValidCredentials( arguments.username, arguments.password ) ) return;
the only thing is that you don’t return a valid authenticated user here. But that makes sense if your credentials are in code
If you want I could demonstrate this in some short zoom session Nolan. But I totally agree cbauth an cbsecurity should work better together.
it is confusing now. If you really hate this flow you could extend the cbauth authentication service, rewrite the authenticate method WITHOUT exception on false credentials. It is quite trivial to replace cbauth with your own version which does exactly what you want
cbauth has some additional goodies though, the interception points https://cbauth.ortusbooks.com/interception-points
I use them right now in one of my current projects. I have multiple users for multiple tenants and on login I have to set the current tenant code in some persistent scope. the postAuthentication interceptor is perfect for that scenario.
p
Yea I also utilize the interception points, quite helpful.
w
I think I spent more time writing blog posts on cbsecurity, explaining people about cbsecurity, fixing bugs in cbsecurity than in writing my own security system instead (which I did long ago before cbsecurity was there). I even hacked cbsecurity to work together with JWT before there was a JWTService
which does its authentication in a different way compared to cbauth 😭
n
Thanks for the help, gents!
I may write up a blog post about this later myself. 🙂
w
Just FYI: cbauth used to work together with cbguard where cbguard was for annotation based permissions and cbauth for authentication. cbsecurity used to work with rules and your own authentication mechanisms Some versions later a lot of functionality was added to cbsecurity including any authentication service based on the cbauth interface and a jwt service for tokens. Although it it more flexible now it certainly is not easier now…