How do I get my ORDS sample service working? - oracle-rest-data-services

I have a working APEX installation, running ORDS in standalone mode, with several applications in use.
I have enabled my schema for ORDS and installed the sample service.
However, when I try to test the https:///ords/rest/hr/employees/ service, I get a 404.
I've tried:
Another schema within the installation, and it doesn't work there either.
Resetting the sample service. Nada.
De-registering and re-registering the schema under a different alias and installing the sample service again. Zip
Why this isn't working?

After much research and trials, I've found the answer:
TLDR: the password for the ORDS_PUBLIC_USER has expired
I found this article that talks about this problem, from which I was able to figure things out.
Apparently, by default, passwords expire after 180 days (of non-logging in?) and the corresponding account is locked. This seems to have no effect on the general operation of ORDS or APEX, since our production environment has been running without a problem for over a year.
The article recommends resetting the passwords of the following system accounts.
APEX_PUBLIC_USER
APEX_LISTENER
APEX_REST_PUBLIC_USER
ORDS_PUBLIC_USER
However, upon running
select * from dba_users where username like 'APEX%'
I could see that only the ORDS_PUBLIC_USER account was locked, so I only dealt with that one.
The article said to use the original passwords from when ORDS was installed, but upon inquiring what that was, I thought it too unsafe, so I decided to change it. That meant two things:
Resetting the users database password with
alter user ORDS_PUBLIC_USER identified by password account unlock;
( change password to your desired password )
Change the password in the corresponding password file, which can be found at a path similar to /ords19/prod/ords/conf/apex_pu.xml and looks like this.
Replace the value of the db.username entry with an exclamation mark, followed by the plaintext password of your choice, and save the file. Thus, if you wanted to use the password foobar, you'd put !foobar. (Don't worry: When ORDS restarts and reads the file, it encrypts the password and writes the encrypted version back to the file so no one snooping around in your filesystem can get at it.)
After I did all this, I restarted ORDS, and voila! My REST sample service now returns data as intended! Thank you Internet.

Related

Firebase Authentication, Password Reset, Different Domain, Causing Chrome Warning

I am hosting with FireBase and using Firebase Auth with SDK for Flutter. If I induce a password reset email then the user is directed to a slightly different domain than the hosting domain for my app, i.e. <domain>.firebaseapp.com rather than: <domain>.web.app, the user then creates the new password and instinctively (90% of users so far) hit 'yes' to saving the password they just set in chromes database.
Then they go to my app and try to login. This is where the issue comes: Chrome detects the same password is in use as has been saved elsewhere, i.e. it spots a saved password for that different domain. As a result it lights up the usual SSL padlock with a big red "dangerous" and gives a terrifying warning saying that my website is deceptive and has just stolen all the users money and probably their dog.
This is an absolute show-stopper. I tried, thinking that human procedure would get me round this quickly, to warn users not to save their new password at the point of setting it, which spectacularly failed, in tests I tried putting the first sentence of the password reset email as "Please do not save your password immediately after setting it, but only when you are at the point of logging into the app." 4/5 testers didn't notice that sentence, they are all too used to password reset emails and ignored all content and just hit the link, the one person who did read the warning refused to go any further as they'd only read first half of sentence and understood that they weren't allowed to save password at all.
I could start creating a new domain and some cnames, but for a start that might not work - I can imagine some SSL issues doing that, also I'd rather liked the domain firebase made. If I went down the route of creating a password reset page myself, I presume I'd have to have named routes in the flutter navigator to accept a url (currently the app never shows any more detail beyond the # and this was quite deliberate), also I guess I'd need to access the token somehow to verify it etc. I'd really rather just use the built in mechanism, even if there isn't currently an option to redirect the user to my app afterwards they perform the reset.
A slightly tangential subject, but I've never come across the 'dangerous' tag in chrome when using the same password on two sites, until this time - for my app... Is there something specific to my flutter web app or firebase hosting causing this? Perhaps instead of dealing with the flow described above I can somehow eliminate that warning? While the warning seems like a reasonable one (using the same password all over the place is a silly), it strikes me as suspicious that I haven't seen it before until it happened on my app.
Thanks for any help

How to provide read backward compatibility after enabling role-based authentication in cassandra?

We are going to change cassandra setting from authenticator: AllowAllAuthentication to authenticator: PasswordAuthenticator
to enable role-based authentication. There will be two roles:
admin which is a superuser
read-only which is only allowed to read.
I would like to provide backward compatibility for users of the cassandra cluster. More specifically,
many users use
shell script that uses cqlsh
python cassandra package
php cassandra package
to only read data from cassandra. Currently they don't specify any username or password. Therefore
I would like to make read-only role some sort of a "default" role, i.e. if no username and password provided,
then the role is automatically set to read-only so the users can read data and thus clients don't need to change their code.
Is there a way to do this? I'm currently having trouble in the following two parts:
the default user is cassandra if there is no role / user specified in cqlsh. I did not find a way to set default user / role.
and for the default user cassandra, I still have to set a password for it.
Any suggestions would be appreciated! Thanks in advance.
I come from an oracle background, were I've done "sqlplus "/as sysdba"" for years. I like it because the O/S authenticates me. Now, there is something similar in Cassandra, but it isn't secure. Basically in your home directory there is a subdirectory called ".cassandra" (hidden). In that directory there is a file (if there isn't, create one) called "cqlshrc" (so ~/.cassandra/cqlshrc). That file you can add authentication information that will allow someone to log in by simply typing "cqlsh" without anything else (unless you're doing remote where you need "host" and "port"). The cqlshrc file has, among other things an authentication section that looks like this:
[authentication]
username = <your_user_name>
password = <your_password>
So you could simply put your desired username and password in that file and you're essentially able to connect without supplying your username and password (You could also run "cqlsh -u your_user_name" and it will find your password in your cqlshrc file as well).
You can see a few obvious issues here:
1) The password is in clear text
2) If you change the password you need to change the password in the cqlshrc file
I do not recommend you use the "cassandra" user for ANYTHING. In fact, I'd drop it. The reason is because the cassandra user does everything with CL=quorum. We found this out when investigating huge I/O requests coming from OpsCenter and our backup tool (as you can see, we use DSE). They were all using cassandra and pounding on the node(s) that had the cassandra authentication information. It's baked into the code apparently to have CL=quorum - kinda dumb. Anyway, the above is one way to have users log in with a specific user and not provide credentials making it pretty easy to switch.
Hope that helps
-Jim

github3.py authorisation lost tokens / multiple machines

I am probably doing something stupid, but...
When attempting to retrieve a token with code like this:
auth = github3.authorize(user, password, scopes, note, two_factor_callback = two_factor_callback)
I'm finding that the API creates a token, which I then store locally, and all is hunky dory.
If however I lose the locally stored token, or move to another machine where the token is not stored locally, I get a failure back from authorize.
It seems that once a token is created for a given note value, it cannot be obtained again, or overwritten with a new one.
For changes of machine, I suspect that the fingerprint parameter in the github API needs to be implemented. A temporary workaround is to salt the note value with something unique to the machine you're on, such as the MAC address, but that's a bit ugly.
For the situation where the token exists, but the local copy of it has been lost (by the user deleting it from the keychain where I've stored it, for example), the only solution seems to be to log on to the github website and manually remove the token!
That's a bit counter-intuitive to me! What am I missing here?
I can see that perhaps github's servers don't store the entire token, so can't return it again - but in that case I'd expect a clean way to be able to regenerate it. Maybe there is one, and I'm missing it?
For the situation where the token exists, but the local copy of it has been lost (by the user deleting it from the keychain where I've stored it, for example), the only solution seems to be to log on to the github website and manually remove the token!
You should be able to access the list of authorizations with the user's username & password. If you can find the existing one, you should be able to delete it.
I can see that perhaps github's servers don't store the entire token, so can't return it again
I suspect they do store it. They just refuse to return it.
but in that case I'd expect a clean way to be able to regenerate it. Maybe there is one, and I'm missing it?
As far as I know, there is no way to regenerate an Authorization Token. GitHub doesn't make the generation algorithm public and there's no way to retrieve a token after it's first generated.

authentication-flows email URL's do not work after web server reset

I have been playing around with authentication-flows and noticed that when I restart the web server the URL's no longer work, they are all invalid. I walked through debugging but I am still a bit lost as to exactly why, though I have a lot of good reasons why it should happen (and I am sure you do also).
I want to make a service which will be distributed to multiple containers and when a request comes in any of them could serve it. As the solution stands right now, it looks like I will have to make modifications to make possible.
What exactly is making the URL invalid? and what changes could I make to make my proposed solution possible?
Thank you in advance.
In response to Ohard's comment:
1. Why the URL is invalid
Let me tell you how I get the error. I deploy the war, submit forgot password. Receive the email to reset my password then stop the war. When that happens my reset password page extracts the enc. I then stop and redeploy the war. After isend a rest request with the enc and a new password to the /rest/setNewPassword mapping, then receive:
09 Jan 2016 03:50:48,799 [http-nio-8082-exec-1] ERROR
web.rest.UserActionRestController - Failed to decrypt URL content
aX8uaOWkqAUQN2xOzlPAOHJjPZaxBwho7.yoMeUtMnJA
in ohadr\crypto\service\CryptoService.java there is an exception on line 261:
throw new CryptoException("Failed to decrypt URL content " +
based64EncryptedContent, e);
which I then use a break point to find:
java aes javax.crypto.BadPaddingException: Given final block not
properly padded
I am sure if you try to reproduce this issue, you will find the same results...
Note: when I do this without the re-deploy everything works great!
2. How to make auth-flows work as SaaS
There are three use cases I want this service to fulfil:
Currently, If I host a service and it goes down without a fail-over, people who have URL's will be unable to use their links when it comes back up. I want them to be able to use the links regardless.
(untested -- but will be soon) Similar to the second, If I host this service on multiple docker containers I believe that it will not be able to receive link that did not orginially come from its container, therefore containers could not share unsorted loads. It should be able to read any of the enc's and process it.
EDIT:
1. Why the URL is invalid
An even easier way to test this is just to submit a forgotten password, get the email and then stop the war. Redeploy it, then click the link. I got this stack trace:
https://drive.google.com/file/d/0Bwa-JXbjFUDueXVMWWJibjY2Zm8/view?usp=sharing
Don't worry about csrf it is not enabled.
1. Why the URL is invalid
As it looks like, the ICryptoUtil instance is re-created after you redoply the war.
CryptoService.java line 38:
return ContextLoader.getCurrentWebApplicationContext().getBean(ICryptoUtil.class);
I suggest for you to do a small test. Encrypt a string twice, now and after the redeploy and compare the results.
If you got 2 different results then your crypto is not capable to decrypt an encrypted string of another crypto instance.
#EdiZ is right.
To be more accurate, every time your web-app loads, Spring loads all the beans. Among them are Crypto's library beans, such as CryptoUtil and CryptoProvider, and if you look carefully you will notice on DefaultCryptoProvider.loadMasterKeys() that a new key is generated.
I believe that explains the behavior you see.
Currently, If I host a service and it goes down without a fail-over,
people who have URL's will be unable to use their links when it comes
back up. I want them to be able to use the links regardless
It seems to be a duplication of your first question; I think that the first issue will have to be resolved in order to make it work as you wish. If the server reboots, all the links become invalid - the users will have to click again on "forget password" (for example) and get a new link - it is for you to decide how big this deal is.
If I host this service and I do have a failover I assume the failover
will not be able to read URL that is not from it originally. It should
be able to read any of the enc's and process it.
I assume that you have to develop some more persistence, so the server can decrypt URLs that were not generated by it...
Hope that helps.

How to migrate passwords to a different hashing method

When changing the password-hashing algorithm for an application, how should the system migrate the values already saved in the database? I am well aware of the fact that I can't migrate them in their hashed form but that I need to have the input data in order to calculate the new hash.
There are two situations in which I have access to the input data:
During login
When the user changes her password in her profile settings
obviously only during one of these I am able to save the new hash to the database to migrate the password.
Although all of my colleagues are voting for method one my gut tells me to not do that. Is there a recommended way?
I see no reason not to do this on logon. Is there a reason you don't want to do #1? You validate against the new hash, if that fails, validation against the old hash algorithm. If that works, I'd then write the new hash over the old one. This means that your passwords will be converted faster, since users probably logon more than they go to change their password. Unless you force people to, I doubt most will change it on their own.
Here's an alternative solution if you don't won't to touch the old authentication code (ie. switching to a new framework) or just want to rid yourself of the old password fields:
Backup the existing table of passwords and then delete all the existing entries in the passwords column in this table (and update the column type if necessary of course) so that it is ready to receive fresh passwords with the new encryption.
The next time users try to log in, check the passwords table and if the user exists with no password, then prompt them with "We have implemented a system wide upgrade and all accounts will need to be re-verified from email. We have sent you an email, please use the email to complete your account upgrade. We apologize for the inconvenience."
The users will go to their email and click a link that may say something like "Re-confirm my account". They will be taken to a page that requires some secure token parameter, received from the link given in the email. This page will now ask them to enter their username and password (more importantly password) to complete the upgrade. You can require they enter the password twice, to guard from typos. Technically, you are creating their password here. Just simply ask for it in 2 inputs labeled "password" and "confirm password".
There are of course both pro's and con's to this solution as well, in comparison to the others. The good thing is you don't have to add old hashing code in your new environment and have it sit there until the one day all your users have finally logged in again. But this solution comes with the price of writing extra code as well (code to send emails/token and so on). You'll have to compare that work to the work involved with your proposed solution of intercepting the form input coming in, checking against old hashing, and then passing onto new authentication code. Just another idea for you.
Look at this IT scenario: Company A Took over Company B with similar business model, All the customers need to be merged into one bigger system owned by Company A, while decommissioning user system in company B which has different password hashing algorithm,
The best Implementation to getting this done is to Force password Change for all migrated users via their registered email address.
It's hard to get specific advice without knowing specifics about the problem. I'm going to assume that the reason you want to change your password storage strategy is because your new strategy is going to be significantly more secure than your existing strategy.
If that's the case, then what's the possible advantage to waiting? The idea is to mitigate the existing risk. Users, realistically, very rarely change their passwords. If you want to migrate to a new storage strategy, you should probably do it at login or you're just going to have a big database full of passwords with dubious security.

Resources