Apex 4.2 LDAP authentication - locked out user - plsql

I have successfully implemented the LDAP authentication in APEX 4.2. I am now trying to extend the functionality by using the policy that users are locked after trying to login x times.
This is correctly used in my LDAP server, a user can not login after trying (atm) 3 times. The problem is that APEX displays this as a failed login instead of a message that the user is locked, so the user has no way of knowing why he can't login.
How can this be displayed accordingly?
I am using PL/SQL, for which the package DBMS_LDAP.simple_bind_s doesn't indicate the reason why the login failed. So I checked out the DBMS_LDAP_UTIL package because this gives more return values. Is this the way to go by adding a procedure checking if the user is locked out, or is there another way?
I can't get the DBMS_LDAP_UTIL.authenticate to work though. I copied the existe_user function mentioned here: http://fdegrelle.over-blog.com/article-1311889.html
Running this says my Authentication failed, although I do use the correct user and password.
Any ideas to help me out? Thanks in advance!

If you want everything the password policy extension provides, you have to use the password policy extended operations and controls. In this case you need to use the password policy request control on the bind operation. Then you will get a password policy response control with the response, that will give you the information you need.

Related

Symfony LDAP bind as current user

So i have Symfony 4 app which should allow login via LDAP and based on your groups modify some of the values in this ldap directory.
The Login itselfs, and mapping from Ldap Groups to ROLE_ works perfectly.
The idea was that only the currently logedin user does a modification. Not a hidden Directory Admin.
For this i would need to $ldap->bind() with the user credentials each time a loged in user wants to modify the directory.
But for this i would need the password. The only way i could think of, would be to save the password in the session - but form a security standpoint this would be a very very bad idea.
Is there any other way? Like store the already binded connection somehow?
As far as I see in the Symfony security component - the UserProvider only refreshes the user from sesison - without calling ldap again.
The LdapBindAuthenticationProvider only uses the ->bind() call with the given credentials and catches an exception if password doesnt match.
But the connection itself is a simple fire & forget.

how to force ownerID when sending a note update on workfront

I can successfully create an update on projects but it seems that I cannot overwrite the thread creator by ownerID.
URL sample:
https://workfronturl/attask/api/note?updates={"noteText":"test","noteObjCode":"PROJ","objID"="projectid", "ownerID":"ownerIDxxxxafda"}&method=POST
Can the ownerID be forced to another user?
If I understand correctly, you want to make an update on behalf of a user. We do this all the time as we have a system that translates updates from another system to Workfront. If this does solve your problem, please be sure to write to Workfront and tell them that they need to leave this functionality in the API in the future. I have confirmed with them that this wasn't supposed to work this way.
So, with regards to solving the problem, you need to do the following:
Login as the user who you want to make an update on behalf of. You can do this without having the users password if you have an API key. Just run the login command as you normally would, but instead of passing in a password, send the username and apiKey.
This will return a sessionID. Use the session ID to authenticate when making your update.
If your system is caching credentials, don't forget to log out or all future updates, changes, whatever, will try to use that session ID.
If you are using Python, we built a function into the workfrontapi_plus (only Python3.x) python library to support exactly this called make_update_as_user. As a note, I haven't managed to publish the documentation for this yet, but the doc strings are there and fully filled out with instructions.

Google OAuth Always Showing Consent Screen

I'm building an installed application that will have features requiring the Google Drive REST API using Qt and C++. I understand Qt is now releasing new libraries to support OAuth flows but let's assume I'm a student and learning to use OAuth at this layer is a requirement for this project.
In my application, I have a working OAuth flow for installed applications that ends with an Access Token and Refresh Token being stored using QSettings (I'm open to input on whether this is a disastrously bad idea too). The application requires no authentication/login for its own sake/data, but it does need authentication to Google for calling API's using an Access Token. This application has no associated web backend being hosted; its simple and should be deployable completely locally (I've written and included a simple TCP server that will receive the authorization redirect_uri and will run and close when called from within the application).
As such, I'm curious about the best way to make sure that, when a user opens my application and wants to use the Google Drive features, they are appropriately authenticated on Google's end. Say, if I maintain an access token in the registry, and this access token is granted per-user/per-application basis (right?), then how can I make sure only the user the token belongs to is able to make calls to the API with it?
Here's my understanding and approach; feel free to correct me or educate me if I've got the wrong interpretation.
If an Access Token is found, perform the following:
Open a browser page to a Google login domain and have the user authenticate there (this could prohibit a user from being able to use a cached login session that would have access to a token they otherwise shouldn't have access to)
If user has correctly authenticated with a Google account, return control to the application and make a test call to an API using the stored token.
If the call fails (responds with an invalid_credentials) I should be able to be sure its because the access token has expired and the application will go through the flow to renew an Access Token from a Refresh Token.
If no Access Token is initially found:
Start a normal OAuth installed application flow
Get the tokens and store them so that when the user opens the application next time the former procedure is used
My issue then is the first two steps if the Access Token is found. Nominally this could be done by the typical OAuth flow but it appears that when using a localhost as the redirect uri, Google will always prompt for consent, regardless of settings for prompt and access_type authorization query parameters.
What can be done to accomplish these first two steps in a way that my application can control (i.e. not a solution that relies on a backend server being hosted somewhere)?
If this question is too open-ended for SO requirements I can make some more restrictions/assumptions to limit the problem domain but I'd rather not do that yet in case I unknowingly rope off a good viable solution.
Thanks for reading! Sorry if its a verbose; I wanted to ensure my problem domain was fully fleshed out!
If you are using an installed application, I wouldn't recommend using or storing refresh tokens. Storing refresh tokens on the client side means that if an intruder gains access to the client's application, they have infinite access to the user's application without ever having to enter the user's credentials. If you do insist on having a refresh token, ensure you follow the Google's installed app flow, with the code_verifier parameter included in your requests.
If the access token is found, you should try to verify it, and if verified then use it at the google api, otherwise force the user to login again (or refresh it if you chose to still use refresh tokens).
If no access token is found, your flow sounds fine.
A few notes on loggin in with Google:
Google will only return a refresh token if you specify access_type=offline in your auth request.
Google will only return a refresh token on the user's first authorization request, unless you always specify prompt=consent in your query params.
In my experience, when leaving out the prompt query param, the user is not prompted for their consent again. If they are logged in to google, you will get a new access token, but no refresh token, unless you have prompt=consent.
I think the idea is you use prompt=consent if you have no record of the user ever using your application. Otherwise if they have used it before, you may prefer to use prompt=select_account to allow the user to select which account he wants to use in case he has more then one, or you can just use prompt=none.
This is just my understanding of it all.
My approach I ended up using was just to deploy with an SQLite db that will be stored in the AppData roaming directory. The db schema includes a field for the user's Name (from the OpenID IDToken field if it exists), the user's picture URL (again from IDToken if it exists), the refresh and access token strings (will be stored as encrypted strings when I get around to it), the user's UID/sub string, and a field for a user name and password.
These latter two fields are authentication fields for within my own application, which, again, I wanted to avoid but it seems impossible to do so. So the user will be prompted to enter a username and password into a form, and these credentials will be checked against the existing SQLite db file mentioned previously.
If they exist and are correct, the user gets logged in and will have access to their respective access and refresh token.
If the user has forgotten their password, they'll be asked for reconsent (going through the installed app flow again), and whatever password they provided during initial login will be used as the reset password. It is considered, for my purposes, that logging into Google for the installed app flow is proof enough that the user account belongs to them and they should have authorization to reset the password.
If the user is a new user and doesn't have a record in the local SQLite db file, then they can also click a button to "Create New Account" - which effectively goes through the authorization flow as well but this time a whole new record is posted to the SQLite db with the appropriate fields filled.
There's still more optimization that could be done but at least I am getting closer to the level of security and control of access to Google user accounts that I want.
I'm not marking this as an answer because I feel like this solution is still not desired and that there should be an easier way. So if someone has evidence or experience of providing an equivalent level of authentication control without needing to maintain a local user account database then I would be more than happy to mark such a method as the solution!
Thanks again!

How two detect that the same users authenticated from different network?

I am using ASP.NET forms authentication, is it possible to detect that two of the same login logged in?
I want this to prevent a situation that two users on the same account modify the same thing. so i want to notify the user that another user of the same login name is already inside the system.
I am also using MemberShip model of .net to authenticate if this helps.
Check out this resource. This approach uses the cache to see if the user has made a login request on another machine. I've seen the database also used as well. The main goal is check to see if the user has gone through the login process, and if they have, block the second attempt to login.

how about allow the user login at the sametime?

In my appliation,all pages are protected,so they must login to visit the pages.
And the admin of the system can add users.
Now some people told me that I have to prevent people login at the sametime using the same account.
That's to say if there is a user named "John" logined to the system,so other people cannot login with "John" again event he know the password.
Also,if one user find that someone have logined use the account he wanted,he can make the former user offline. If so I have to judge if the current user have been offed ornot in each page. This is not a work can be done easily.
I wonder if this is necessary?
Since I found so many websites nowdays do not limit this,for exmaple,you can use the same account login your gmail/stackoverflow/yahoo and ect in different machine at the same time.
So Any one can give me a suggestion?
Update:
Now,we use the asp.net's form authenciation,(we do not use the membership yet). And in the t_user table in the databse,we have a column named "isOnline" and "last_login_time".
When user login,we set the "isOnline" to 1,and store the login time.
When another user try to login again,we check the "isOnline" and the time:
if("isOnline"==1 && DateTime.now-LastLogiTIme <40min) // where the 40 min is the form authenaication timeout.
thisAccountHasLogined=true;
But suppose a user logined yet,then he clean the browser cookie,then if he refresh the page,he will be redirected to the login page,but not he can never login again before the form authentication time out because the "isOnline" in the db is 1 and the time span from his login to now does not large than the form timeout.
I am confused.
In some scenarios, I could understand not having multiple logins, but in reality, I have never had to implement it.
Unfortunately, I do not believe there is a standard mechanism for determining if a user is already logged in and this would need to be done by additional logic. In our application, we use a database for storing session information and using this, it would be a simple process to see if a session already exists within this for the user and not allow login if so.
Update
I was interested in this myself and found this;
http://msdn.microsoft.com/en-us/library/system.web.security.membershipusercollection.aspx
and this
http://msdn.microsoft.com/en-us/library/system.web.security.membershipuser.aspx
Using those, it may be possible to get this information with the .IsOnline() However, this does make the assumption you are using standard asp.net membership
the table where you store user name and password add a column status
when a user attempt to login update status to "Online" when logout update status "Logout"
During login check status, if status is online , terminate process. This may be an approch to implement this, hope it will help you

Resources