Not sure if the question should rather be on ServerFault?
I have a couchDB setup on my server using Apache credentials (but I can switch that off if it is an distraction).
I have local instances on various laptops. Now I want to setup secure (continuous) replication. From my understanding I could use username/password, SSL certificates or OAuth. I found bits and pieces of information:
SSL Question on serverFault
the WIKI entry on replication
how to on replication in the wiki
the gist on 1.2 replication
the replication algorythm
All this documents added a hunch, but also confusion (I'm just a simple mind).
What I'm looking for is a step by step instruction:
Pro and con for OAuth or SSL certificates (optional discussion)
Steps to setup the SSL components Clarification: I'm not looking for SSL transport security - that's not really complicated and documented well for both Apache HTTP and CouchDB. What I'm looking for is authentication using certificates, similar to what you can do in SSH. The potential problem I see with OAuth: a admin has full access to the credentials (?). With a certificate approach (s)he can't impersonate the user since the private key is not under admin control.
Steps to setup OAuth
Sample replication documents for the each user uses a local replica with some documents and share one oneline
Where could I find that?
Secure transfer of user credentials is a very delicate question.
If we wouldn't look on third-party, in most cases, SSL is better way to start from since it has wide support by every tool you might used. SSL certificate, provides not only encryption (even self-signed ones), but insurance that user had requested right resource. Last option also worth to be highlighted if you're care about server security. The main drawback of SSL usage is performance degradation (vary on used algorithm) since server have to decrypt data and client need to validate certificate in additional to common communication routines. Also you have to pay some money for trusted certificate (not always true).
Using OAuth allows to not disclose real user credentials and easily maintain their access control from server side. Also, you need some library that handle OAuth 1.0 specification properly and if your platform miss such - you have to implement it by your own. In additional OAuth provides transfer data signing, so it aims to be safe for MiTM case. That's actually all that he does.
As you note, SSL and OAuth are about two different things: SSL helps to encrypt data on transport level (TLS) while OAuth take care about credentials disclosure in non secure environment. They are not replacement for each other, but each of them may stand as good additional to other.
To setup SSL support for CouchDB just follow the documentation guide. It's quite simple and easy to do. Note, that if there is some proxy server in front of CouchDB, it might be wise to setup SSL for him and proxy data to local CouchDB instance via regular HTTP protocol.
To setup OAuth there need to make next steps:
0. Ensure that {couch_httpd_oauth, oauth_authentication_handler} handler is exists for authentication_handlers option of [httpd] section for default.ini config file:
[httpd]
authentication_handlers = {couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}
After that you need to edit your local.ini file in next way:
Setup consumer secret:
[oauth_consumer_secrets]
example.org = sekr1t
Setup token secrets:
[oauth_token_secrets]
token1 = tokensekr1t
Map tokens to existed CouchDB user:
[oauth_token_users]
token1 = joe
That's all! If you have CouchDB version 1.2 or higher, you may also define OAuth credentials within user document inside _users database:
{
"_id": "org.couchdb.user:joe",
"type": "user",
"name": "joe",
"password_sha": "fe95df1ca59a9b567bdca5cbaf8412abd6e06121",
"salt": "4e170ffeb6f34daecfd814dfb4001a73"
"roles": ["foo", "bar"],
"oauth": {
"consumer_keys": {
"example.org": "sekr1t",
"consumerKey2": "key2Secret"
},
"tokens": {
"token1": "tokensekr1t",
"token2": "token2Secret"
}
}
}
Now, when we'd setup OAuth credentials for our user joe, let's start our replication. To let CouchDB use OAuth credentials, we need to extend source or target fields, depending on which side will authorize our user:
{
"source": "mailbox",
"target": {
"url": "https://secure.example.org/mailbox",
"auth": {
"oauth": {
"consumer_secret": "sekr1t",
"consumer_key": "example.org",
"token_secret": "tokensekr1t",
"token": "token1"
}
}
}
}
and POST this data to _replicate resource or create document for _replicator database. Replication will start from local server to remote secure.example.org using SSL protocol encryption and all operations will goes for remote user with login joe.
Summarizing: combination of SSL and OAuth allows you not only protect transfered data (not only user credentials) and insure that target server was not faked, but also protects real user login name and password from accidental disclosure, control consumer sources (e.g. if example.org will be compromised, we can only remove his consumer token, but not force user to change his password) and signing requests for additional protection against MiTM attacks.
UPDATE: For your case regular SSL certificate routines are ok: you will need to create personal certificates signed by your own and let clients to setup for further work with your CouchDB. The only thing required from CouchDB side is to validate certificates before process the connection. But note, that custom personal SSL certificate installation may be not trivial especially for mobile clients.
Speaking for OAuth side, CouchDB may use RSA-SHA1 auth method that uses some kind of personal certificate for secret. However, you need to patch sources first to unlock this method - it's disabled by default.
Related
I'm using Oracle Application Express 11g.
To secure RESTful services I want to create Third Party Authentication for it.
According to this article : http://www.oracle.com/technetwork/developer-tools/rest-data-services/documentation/listener-dev-guide-1979546.html
In order to register my third party user I need to access this url : https://server:port/ords/resteasy/ui/oauth2/clients/ as I don't have SSL every time I face this error(entring the url in http) :
403-Forbidden
This resource must be accessed over HTTPS only
The Question is : how can I disable "security verify SSL" in apex, in order that I never face this error again.
Note that there is no error like this in other pages because I'm not forced to use https, and I'm receiving this error entring the url in http.
https://docs.oracle.com/cd/E37099_01/doc.20/e25066/install.htm#AELIG7183
1.4.5 Using OAuth2 in Non HTTPS Environments
RESTful Services can be protected with the OAuth2 protocol to control access to nonpublic data. To prevent data snooping, OAuth2 requires all requests involved in the OAuth2 authentication process to be transported using HTTPS. The default behavior of Oracle REST Data Services is to verify that all OAuth2 related requests have been received using HTTPS. It will refuse to service any such requests received over HTTP, returning an HTTP status code of 403 Forbidden.
This default behavior can be disabled in environments where HTTPS is not available as follows:
Locate the folder where the Oracle REST Data Services configuration is stored.
Edit the file named defaults.xml.
Add the following setting to the end of this file just before the </properties> tag.
<entry key="security.verifySSL">false</entry>
Save the file.
Restart Oracle REST Data Services if it is running.
Note that it is only appropriate to use this setting in development or test environments. It is never appropriate to use this setting in production environments because it will result in user credentials being passed in clear text.
I'm trying to add OTP/2FA support into OAuth2, but after much reading through the RFC6749, it's still not clear how OTP/2FA could be cleanly added without violating the specification.
Although OTP/2FA entry can be added into the authorize dialog flow, there is no provision for adding it into token. For example, public client apps with Resource owner password-based privileges may want to provide the token directly when requesting a new access_token, rather than having to embed a HTML dialog box.
Therefore my questions are;
Does the RFC allow for custom grant_type? Should this be used to provide 2FA/OTP functionality?
Does the RFC allow for additional attributes on an existing grant_type? For example, grant_type=token&otp_code=1234 (RFC does not make it clear if additional attributes are allowed on grant_type's within the specification)
Should OTP functionality be placed into headers? This is the approach that Github used, but it feels really ugly/hacky.
Are there any other approaches that I have overlooked?
Thank you in advance
The RFC allows for an extension (custom) grant, see section https://www.rfc-editor.org/rfc/rfc6749#section-8.3. That grant could define additional attributes.
OAuth 2.0 does not define how the Resource Owner authenticates to the Authorization Server, with the exception of the Resource Owner Password Credentials grant. Your proposal could be designed as an extended variant of that grant.
I'm working on something similar. I've got an endpoint at which you can request certain metadata for a user such as whether or not 2fa / mfa / otp is turned on and the salt (and iterations and algorithm) for Proof of Secret / Secure Remote Password.
If you go that route you can simply extend the grant types with an mfa or totp field (that's what I'm doing). You could also create a custom grant type as mentioned above (perhaps more proper).
Another solution is to check for MFA / 2FA / OTP during the authorization dialog step.
If I were done with my OAuth2 implementation I'd link you to that code too, but here are some libraries for an Authenticator:
Browser Authenticator has the components you need to generate and verify a key and token in the browser: https://git.coolaj86.com/coolaj86/browser-authenticator.js
Node Authenticator has the complementary server-side code: https://git.coolaj86.com/coolaj86/node-authenticator.js
You would still need to provide your own database storage mechanism and link it in to your OAuth implementation or you could make a very simple one and run it as a microservice.
I agree with Hanz Z.: you can design your own grant type to consume OTP.
But OTP can also be used for client authentication (confidential clients as you have to store credentials).
For example, we could imagine an header in the token request (X-OAuth2-OTP = 01234567). Client authentification will fail if the client activated OTP but no header is set.
Based on specifc SCOPE (Ex. OTP) you can mark bearer(access_token) as ""verified_otp = false"" on the backend, then after authorization server received valid otp for that session mark your bearer(access_token) as ""verified_otk = true"". For your resource server, check verified_otk field befores authorize calls that depends this verification.
How safe is it to use LOGON32_LOGON_NETWORK_CLEARTEXT?
We have the following scenario:
Web server A is using Win32 LogonUser. Then it needs to invoke an asmx method on server B.
If the used logon type is LOGON32_LOGON_INTERACTIVE it works well. However the customer rejects this because it requires interactive access.
If we use LOGON32_LOGON_NETWORK this does not allow token delegation to the remote server and we get 401 (as expected, according to the MSDN).
Attempting to use DuplicateToken to "upgrade" the token to interactive fails. This attempt was based on this article where it states:
"When you request an interactive logon, LogonUser returns a primary
token that allows you to create processes while impersonating. When
you request a network logon, LogonUser returns an impersonation token
that can be used to access local resources, but not to create
processes. If required, you can convert an impersonation token to a
primary token by calling the Win32 DuplicateToken function."
But it seems that if we use LOGON32_LOGON_NETWORK_CLEARTEXT as stated in this old thread, delegation works. But how safe is it for usage? According to MSDN:
"This logon type preserves the name and password in the authentication
package, which allows the server to make connections to other network
servers while impersonating the client. A server can accept plaintext
credentials from a client, call LogonUser, verify that the user can
access the system across the network, and still communicate with other
servers."
Are the credentials used in this format visible in anyway to sniffers (we're using Windows Integrated security, sometimes with SSL but not always).
Please advise.
I had the same question, and though I haven't found a definitive answer I've done some investigating and reading between the lines, and this is my conclusion (corrections welcome):
The ideal/safest use case is if your code looks like this pseudocode:
success = LogonUser(username, domain, password,
LOGON32_LOGON_NETWORK_CLEARTEXT, provider, out token)
if (success) {
StartImpersonation(token)
remoteConnection = AuthenticateToRemoteServer()
StopImpersonation()
CloseHandle(token)
// continue to use remoteConnection
}
The plaintext credentials associated with the LogonUser session will be destroyed when you close its handle (I haven't found a reference for this, but it doesn't make sense to me that they wouldn't). So for the lifetime of the token there was a copy of the user's credentials and it was used to authenticate to the remote server. But your application already had the credentials in memory in plaintext (in the variables username, domain and password) so this doesn't really present a additional security risk.
Any authentication with a remote server that uses Windows authentication will be using NTML or Kerberos and neither protocol sends the credentials on the wire, so that's not a concern. I can't say for sure what would happen if the remote server asked for basic authentication, but I think it's more likely that it would fail than your credentials would be sent over.
If you need to keep the token around longer, the documentation does state that the credentials are stored in plaintext (somewhere). I took a dump of a test process and wasn't able to find them in the dump file, so I don't know if that means that they are stored in kernel memory or what. I would be a little worried if I had to keep this token around for a long time.
I use OAuth 2 for authorization and need to implement it in a load balanced cluster. I've considered a few approaches, but it seems there is no way around a centralized approach. Here are my thoughts:
1. Balancing using source IP
Caching the tokens on one server and balancing by IP would be ideal, however, the IP can not assumed to be static. So when the same user tries to access services that require authorization from another IP with a valid token, it will fail, because it is not cached on this machine. Also other devices logged in with this user will not reach the same machine.
2. Balancing using a load balancing cookie
Also not really an option, since it cannot be assumed that every client implements cookie storage.
3. Balancing using the Authorization header
Balancing by hashing the Authorization: Bearer token header is problematic, because the first request (for requesting the authorization token) has no Authorization header, thus, the following request might not hit the same instance.
My current approach is to use a central Redis instance for authorization token storage.
Is there an option left, where a centralized approach can be avoided?
I think you still have two options to consider.
One is to balance by session ID. Application servers usually can be configured to manage sessions either by cookie or a GET parameter added to every link, so it does not definitely needs cookie storage. Additionally, there are very few HTTP clients left that still do not implement cookie storage, so you may want to reconsider item 2 of your list.
The other one is using self-contained tokens, e.g. JSON Web Tokens (JWT) with signatures (JWS). Validation of self-contained tokens may not need central database, each server instance can check token signatures alone and extract authorization details from the token itself. However, if you need support for revoking tokens, you may still need a central database to store at least a blacklist of revoked tokens.
Though I cannot provide you a full-fledged solution, hope this gives you some ideas.
we have a lot of users on a VBulletin forum. now i want write few more apps on rails for the same userbase. Until now all the authentication and session management is being taken care of by VBulletin. What is the best way to provide SSO for my users both onVBulletin and on the rails apps i am writing
I am working on single sign-on process with v Bulletin and custom made application. i can logged in at Vb using cookies. i can access all. but when access send "Private Message". it says
"
You have turned off private messages. You may not send private messages until you turn them on by editing your options.
"
is there all permission are set at "datasource" table?..
Thanks
master
Ideally your two sites are subdomains of a common domain (e.g. forum.example.com and rails.example.com), or share the same domain (www.example.com.) One of the sites would be the primary authenticator, and set a cookie (for .example.com in the case of the common parent domain [notice the . before example.com] or www.example.com in the case of the shared domain, so that both applications can access it), where the cookie contains:
the user ID
a salt (random value calculated at login time), and
a SHA-2 signature computed over the triplet (user ID + salt + a shared secret key), where the shared secret key is a secret string known by both sites.
Each site would be able to retrieve the user ID and salt from the cookie, then use the shared secret key (known only by the two applications) to calculate a SHA-2 signature that must match the SHA-2 signature stored in the cookie.
If the SHA-2 signatures match then you can assume that the user is authenticated, otherwise force the user to log in again.
The cookie must be destroyed when logging off.
The small print
To protect against session hijacking, all requests made over the two sites should be encrypted over SSL (use https.) If this is not possible, a hash based on the client's IP address as well as browser type and version (User-agent) should probably be calculated at login time and also be stored in the cookie. It should be re-checked against the client's IP address and user agent before serving each request. The hash-based approach is security through obscurity, and can be fooled; moreover, a user accessing the internet from behind a pool of proxies or using TOR may be kicked out by your system every time a different proxy or exit node (with a different IP address) forwards a request.