Authenticate user in a controller and send session to frontend - authentication

On backend in a controller, I want to log in a user. Then I want to render a view render(view: '/my-view') where the user will be authenticated already.
Scenario
A user is given a link.
He goes to this link.
Backend redirects the link to a controller.
Controller creates a temporary account for the user and authenticates him.
Controller renders a view and ???? somehow sends the session to frontend ????.
How can I send the session to the frontend?

Define front end ?
Backend redirects the link a controller. Controller creates a
temporary account for the user and authenticates him.
This is how I am doing it sockets does authentication, access that user's http session from backend and puts in there that they have logged in. I then send a socket trigger back to front end html to say all ok
at this point gsp gets response from sockets and says aha redirect to /site/hello
Controller renders a view and ???? somehow sends the session to frontend ????
This /site/hello now checks for specific session and well user is also now logged in too.. the session details was set by backend when user authenticated and not front end session
in gsp you can do
<g:set var="something" scope="session"/>
But I think what i have described is what you need to do
If you need helping user session details it is all quite easy i don't have it to hand
but from gsp when connecting to sockets i send '${session.id}' which then i look up and bind back to user .....
Also note --- there is catch here, when user is not authenticated they have primary session, when they authenticate through spring security they are actually given a new session id. This is due to security issues but I have got around that with checking session.username which i set upon login and this now matches '${params.encryptedUsername}' decrypted on backend..
Ahh it's rolling back.. there is a concurrent hashmap which contains username,session and from that When i get Decrypted.username I get hashMap which the value is user http session to which i poke and do things with ...
I can give you my code but then that is a lot of work above is the steps in one way of how you go about it
So to answer your question, this is under grails 3:
Enable Spring security session listener in application.groovy
grails.plugin.springsecurity.useSecurityEventListener = true
Add CustomSecurityEventListener.groovy class to your app, remove the loginCacheAttempt, unless you wish to use it refer to build.gradle for that stuff and the related service etc in that demo app.
This then calls SessionListener provided in that same folder and adds user with session id to the sessions synchronised map declared at the top of SessionListener
Now in my websockets when I register a user:
String sessionId = userSession.userProperties.get("sessionId") as String
def userHttpsession = SessionListener.sessions.find{it.key==sessionId}?.value
userHttpsession.username = username
userHttpsession.password = password
This is still pre-authentication and primary session
I send a trigger to tell sockets to refresh gsp page to another window.location.href
In that location controller action i authenticate session details and invalidate session details
registerService.authenticateUser(user, session.password)
This way of doing things appears to work fine without the complications, there is an encrypted user which is sent as part of initial socket transaction to ensure/verify session.user matches encrypted user (for logged in user)

It seems like the programmatic login takes care of the session too.
springSecurityService.reauthenticate(email, password)

Related

WebAPI how to disable another user from the admin

I have created a simple WebAPI in Visual Studio C# to act as my backend to Angular.
Users can register via the Angular frontend and passed to a controller in the WebAPI to register that user in the backend DB (MSSql). All fine.
I am using token authentication from Angular to my API and using claims and roles to verify the user is logged in and has access to the requested controller.
How, as an Admin, can I disable another user so they are instantly locked out?
An example would be: A rogue user starts abusing the Angular application and I need to lock them down instantly and not to wait until their token expires and they are required to login again.
I could do a check in each and every controller to lookup the user in the DB and check their status and if I have set their status to "locked-out" then return say a 403 forbidden status from the controller but this seems a lot to lookup the user for each DB request they make.
Is there a "dot-net" way of doing it? I would love to be able, as the admin, to instantiate the said user, change their claim value for "status" to "locked-out" and I simply check their claim when making api requests but I can't see a way of changing another users claims.
Any ideas?
Thank you.
Expanding on my comment above, we have a handler in our pipeline that handles Authorization. We do look at that Authorization header and parse it but all of the controllers rely on the already-parsed value that we hang in the Properties collection. That way all AuthZ/AuthN occurs in this handler and whatever the handler sets in the Properties collection is what all of the application sees.
In your case the handler would need to be able to check whatever throttle or lockout you are using and replace the actual claims received with your "user is locked out" claims instead.

Laravel - recreate cookie login

I am creating an application which hits an external service (db) to see if a user is authenticated.
so:
User submits username and password -> hit service -> returns false or user row from db
Where i am stuck is i now need to login the user into my laravel app. I am thinking what i need to do is something like:
Auth::login($user);
And mimic Laravels User Object
or recreate laravel's encrypted cookie, so the application thinks the user is logged in.
I do not have/want access to the db that the external service uses. That is not an option
Any ideas on how to do this?
Thanks
Brian
http://laravel.com/docs/4.2/security#manually
If you need to log an existing user instance into your application,
you may simply call the login method with the instance:
$user = User::find(1);
Auth::login($user);
This is equivalent to logging in a user via credentials using the
attempt method.

How to implement "remember me" using ServiceStack authentication

I am trying to implement a Remember me feature in a ServiceStack-based project. I don't want to use Basic Authentication because it requires storing password in clear text in a browser cookie, so I need to come up with an alternative approach that will be easy to maintain and customized to my existing database.
I understand that ServiceStack's own support for Remember me is based on caching the IAuthSession instance in the server-side cache, which by default is an in-memory data structure that is wiped out when the website restarts (not good). Alternatively, the cache can also be based on Redis or Memcached, which is better (cached data survives website restarts) but adds more moving parts to the picture than I care to add to it.
Instead, I would like to implement the this functionality using my own database:
Table Users:
UserID (auto-incremented identity)
Username
Password
Email
Name
etc...
Table Sessions:
SessionID (auto-incremented identity)
UserID (FK to Users)
StartDateTime
EndDateTime
SessionKey (GUID)
The way I see things working is this:
On login request, AuthService creates an empty instance of my UserAuthSession class (implements IAuthSession) and calls my custom credentials provider's TryAuthenticate method, which authenticates the user against the Users table, populates UserAuthSession with relevant user data and inserts a new record into the Session table.
Then the auth session is cached in the in-memory cache and ServiceStack session cookies (ss-id and ss-pid) are created and sent to the browser.
If the user checks Remember me then additionally my custom credential provider's OnAuthenticate method creates a permanent login cookie that contains the user's username and the auto-generated Sessions.SessionKey. This cookie will help us track the user on subsequent visits even if the auth session is no longer in the cache.
Now, suppose the site has been restarted, the cache is gone, so when our user returns to the site his auth session is nowhere to be found. The current logic in AuthenticateAttribute redirects the user back to the login screen, but instead I want to change the flow so as to to try to identify the user based on my custom login cookie, i.e.:
look up the latest Sessions record for the username extracted from the login cookie
check if its SessionKey matches the key in the login cookie
if they match, then:
read the user's data from the Users table
create my custom auth session instance, fill it with user data and cache it (just like at initial login)
insert a new Sessions record with a new SessionKey value
send back to the browser a new login cookie to be used next time
if the keys don't match then send the user back to the login screen.
Does the above logic make sense?
Has anyone already implemented anything similar using ServiceStack?
If I were to proceed with this approach, what is the best course of action that doesn't involve creating my own custom version of AuthenticateAttribute? I.e. which hooks can I use to build this using the existing ServiceStack code?
This is already built for you! Just use the OrmLiteCacheClient.
In your AppHost.Configure() method, add this:
var dbCacheClient = new OrmLiteCacheClient {
DbFactory = container.Resolve<IDbConnectionFactory>()
};
dbCacheClient.InitSchema();
container.Register<ICacheClient>(dbCacheClient);
I am not sure when this particular feature was added, perhaps it wasn't available when you originally asked. It's available in v4.0.31 at least.

Problems configuring user authentication by external API on Symfony2

I have a problem authenticating users for my new Symfony2 application.
This applications gets all the info through an API, so no database is used. When a user goes to login page, he introduce the user and password in the login form. Then, I have to authenticate him using an API call. This API call returns "false" if it's not a user, and return a token key and a token secret if its a correct user. With this token key and secret, during the user session, I can make all the API requests I need for rendering all the pages of the application. Once the user session is over and token key and secret are erased, the user has to login again.
I don't know really how ti implement that. I read this http://symfony.com/doc/current/cookbook/security/custom_provider.html and that http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html, and I'm still so lost... :(
Can any one help me?
Thank you so much :)
If you want to write custom authentication you have found the correct links. As an example you can see the implementation of the OAuth authorization HWIOAuthBundle. But keep in mind that this type of authentication creates a user on your system. If you do not use a database, you must make a request to the API every time user send a request.
First you need to understand that there is no magic. On every request symfony checks if url matches one of the specified firewalls (see secutity.yml). Listener that fired you can see in the firewall factory. If matches are found, the action switches to the corresponding AuthenticationListener. Listener attempts to authenticate the credewntials by creating Token, which is sended to AuthenticationProvider
$this->authenticationManager->authenticate(new UsernamePasswordToken($username, $password, $this->providerKey));
in AuthenticationProvider
public function authenticate(TokenInterface $token) {
...
}
AuthenticationProvider try to get user via UserProvider. In case of success, Token stored in the session. On subsequent requests, ContextListener comes into play first, checks the session, extract token and send it to AuthenticationProvider similar.
In general terms, the scheme looks like that. More info you can find examining the source code of Symfony Security component.
Really good starting point is a UsernamePasswordFormAuthenticationListener. It just take login and password from request and make simplest UsernamePasswordToken.
protected function attemptAuthentication(Request $request)
{
...
}
Good luck!

Previous user picked up with auth_token login in Devise

Here's my scenario.
First, I log in as Alice:
http://localhost:3000/?auth_token=eMXBk8cuJMA1ETZfMIgB
Then, without logging out, I log in as Bob:
http://localhost:3000?auth_token=Z9Ui7Cw_xCnOmGWOEUEH
What happens is, after the second GET request, I'm still logged in as Alice, not Bob.
If I do a http://localhost:3000/users/sign_out in between the two auth_token logins, everything's OK.
Without the sign_out, Bob can't login using his token.
Is this a bug, or the way things should be due to some security issues I'm ignorant of?
Can this behavior be overriden through hooks?
I've run into this with restful_authentication and devise. Here is what I use to handle it (put in application_controller.rb) and call it where needed. Note that I use :ak for the auth token. Change to whatever you're using.
def switch_session(api_key_passed)
if api_key_passed != current_user.authentication_token
logger.info("******Switching session as token is different.*******")
user = User.find_by_authentication_token(api_key_passed)
sign_out(user)
if #api_login_enabled.present?
redirect_to(new_user_session_path(:ak => api_key_passed))
else
logger.info("***API Login Setting is Disabled.***")
end
end
end
Devise's token_authenticatable strategy is a login path. Sending a User's authentication_token to Devise will log in that user and set a session, just as logging in via the web would. It is not supposed to act as an API Key, which would be required to be sent on every request and knowledge of that request disappears once the server responds.
Take a look at this issue here for more information: https://github.com/plataformatec/devise/issues/300
#jschorr's answer will work if you wish to use it more like an API key, but you should be aware that the original issue will not actually persist the previous user's session between different clients, this is not a security issue of sessions leaking between clients, and this is exactly how the authors of Devise intended. Just as you would need to log out of your Significant Other's webmail account in order to check your own if they just checked their mail from the same computer, you would need to send a logout message to your Rails app before you can switch accounts.
You are missing a setting on devise.rb initializer:
# By default Devise will store the user in session. You can skip storage for
# :http_auth and :token_auth by adding those symbols to the array below.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing :skip => :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:token_auth]
So no session is used when a user authenticates with an auth_token.