How to keep client secret for OAuth2 login to Parse server secure? - objective-c

I want to enable users in my macos app to be able to securely login to my Parse Server using third-party Oauth2 login. I have been searching for the best approach to do this, but still have some problems. If I understand correctly, logging in requires:
Enable oauth in my Parse server config file (for twitter, google etc).
Get the access token to the provider (e.g. twitter) using a client side OAuth login. I am currently using OAuthSwift.
Login to Parse using the provided access token (from 2) as suggested in the swift example provided here, i.e.
[[PFUser logInWithAuthTypeInBackground:provider authData:authData] continueWithBlock:^id(BFTask<id> *task) {
return task;
}];
This login approach requires the use of the client key and client secret for each provider. How can I safely store these keys-secrets on my Parse server and access them programmatically? Should I use PFConfig and access them during runtime? Is that safe? Or is there something I am doing very wrong here? If anyone has a better approach or an example as to how I should enable OAuth login I would appreciate it (since I am on macos I can not use TwitterUtils and FacebookUtils).

No secret key should ever be used on your client. The client key can be considered "public", and is actually optional (though recommended).
Your secret key should only be stored on your server, preferably as a config/env variable (Note: NOT PFCONFIG). Any use of it should be on your server, and you can create a cloud code function that will use the key as needed and return necessary values to your client. The client should call this, receive a key you need, and then use it appropriately.
Although I'm also not familiar with a client secret key in general? This is the first I've seen of it. I wonder if you've misunderstood any documentation?

Related

Using AccessToken in a secure way

I have a NextJS web app and I'm adding firebase authentication to it.
I want to make secure GET calls to my server, and was wondering what is the token I should use with the server and where to set it?
Should I use the firebase user's AccessToken?
And should I send it in the URL query parameter (or header)? Aren't both alternatives exposed to whomever sees the URL and they can impersonate the user?
Thank you in advance for the help.
Are you talking about your API keys? if you are they are supposed to be visible, you need to write Security Rules which are pretty simple to use.
Read more here: Learn about using and managing API keys for Firebase
If you want your own server-side code to use the caller's Firebase Authentication credentials to ensure they are authorized for the operation they are trying to perform, you should:
Pass the users ID token from the client to your server over a secure connection. This is typically done in the Authorization header of the HTTP request.
On the server decode the ID token, and then check your own authorization logic to see if the call is allowed.
The entire process is quite well described in the Firebase documentation on verifying ID tokens, so I recommend checking that out too.

OAuth2 Resource Owner Password Credentials with Dynamic Client registration

I am implementing login within a new native application (iOS and Android) and deciding on the kind of authentication to adopt. There are some quite clear guidelines around OAuth that state that this should be done using an external agent (browser) and this leads me to Authorization Code Grant with PKCE
https://www.rfc-editor.org/rfc/rfc8252
Implementation here: https://appauth.io/
However, my designers and product owners are sceptical. They dont see that kind of login very much (they dont like the address bar) and want to explore the Resource Owner Password Credentials option. Essentially direct login. Their argument is that it is simple and familiar.
I dont want to compromise security and as such I am resisting this option. But... I have read some articles that seem to suggest that this could be secure if I dynamically generate the client used for the auth request:
https://www.rfc-editor.org/rfc/rfc6749#section-10.1
The authorization server MUST NOT issue client passwords or other
client credentials to native application or user-agent-based
application clients for the purpose of client authentication. The
authorization server MAY issue a client password or other credentials
for a specific installation of a native application client on a
specific device.
This is backed up by AppAuth documentation here:
https://github.com/openid/AppAuth-Android#dynamic-client-registration
https://www.rfc-editor.org/rfc/rfc7591
Am I interpreting this correctly? I am considering initial user registration in-app that returns an access token that can be used to dynamically generate a client (with secret) that can be used for login using ROPC.
I am thinking to be secure then this dynamically generated client should only be used for login for the single user - one client per user, but maybe one client per device is also secure enough.
It seems a little 'hand rolled', so I am nervous. Am I right to be so?

What is best suited to interface with authentication servers for a CLI tool?

I am developing two linux programs, a CLI client and a server communicating via gRPC, and I now would like to authenticate users against a given private authorization server such as LDAP, Active Directory, etc.
I am confused regarding the various possible authentication flows. I think I can't use any classical flow including HTTP redirects since I shouldn't rely on a browser being installed or having internet access. I can't even define an endpoint I could redirect to (servers don't have internet access, and both are behind NATs).
So I was thinking of trying to store user's credentials as a JWT token file in the user's computer and then load it from my CLI client program to include it in my RPC requests and then validate it on the server-side. But, supposing I'm right, then what would be the best standard way of getting this token file?
If you had a browser you could use OAuth and the 'oob' (out of band) method where the CLI opens the browser and after the user authenticates it displays a number which the user copy/pastes into the CLI. This how my flickr backup CLI works. The number they copy/paste is because the CLI has no OAuth endpoint and the number is their access token to allow me to call the flickr api on their behalf.
If you can't use a browser the CLI can just accept a username/password from the user, send it to the server and receive a token in return. You don't really need anything fancy like JWT. A simple UUID would be enough. The UUID 'asserts' that the user is allowed to access the server's other RPC methods. The server would validate the UUID token to make sure it's still valid. If you need user information from the token, the server could do that. Keeps the user information off the client's disk and only the CLI can access that information, if the token is still valid.
So in effect, you need a new server RPC method, perhaps, authenticate, that accepts a username and password and returns a UUID token. All other RPC methods then need to accept that token and validate it before performing the requested function. As part of the server-side authentication process, the server could associate that token with the user information it got from the LDAP server so you don't need to store that information on the client. Lets you encrypt it on the server too and if the client needs it, it asks for it using the UUID token if it's still valid (time to live?). If it's no longer valid, the client just needs to ask for username/password again and the server can re-authenticate the user via LDAP and refresh the token and user information.
gRPC has authentication protocols but the SSL/TLS doesn't seem to match your needs and the OAuth won't work as you don't have a browser. So perhaps rolling your own simple token service (authenticate) combined with LDAP authentication might be a workable option.

Where to store client secret for mobile app? [duplicate]

When using the OAuth protocol, you need a secret string obtained from the service you want to delegate to. If you are doing this in a web app, you can simply store the secret in your data base or on the file system, but what is the best way to handle it in a mobile app (or a desktop app for that matter)?
Storing the string in the app is obviously not good, as someone could easily find it and abuse it.
Another approach would be to store it on your server, and have the app fetch it on every run, never storing it on the phone. This is almost as bad, because you have to include the URL in the app.
The only workable solution I can come up with is to first obtain the Access Token as normal (preferably using a web view inside the app), and then route all further communication through our server, which would append the secret to the request data and communicate with the provider. Then again, I'm a security noob, so I'd really like to hear some knowledgeable peoples' opinions on this. It doesn't seem to me that most apps are going to these lengths to guarantee security (for example, Facebook Connect seems to assume that you put the secret into a string right in your app).
Another thing: I don't believe the secret is involved in initially requesting the Access Token, so that could be done without involving our own server. Am I correct?
Yes, this is an issue with the OAuth design that we are facing ourselves. We opted to proxy all calls through our own server. OAuth wasn't entirely flushed out in respect of desktop apps. There is no prefect solution to the issue that I've found without changing OAuth.
If you think about it and ask the question why we have secrets, is mostly for provision and disabling apps. If our secret is compromised, then the provider can only really revoke the entire app. Since we have to embed our secret in the desktop app, we are sorta screwed.
The solution is to have a different secret for each desktop app. OAuth doesn't make this concept easy. One way is have the user go and create an secret on their own and enter the key on their own into your desktop app (some facebook apps did something similar for a long time, having the user go and create facebook to setup their custom quizes and crap). It's not a great experience for the user.
I'm working on proposal for a delegation system for OAuth. The concept is that using our own secret key we get from our provider, we could issue our own delegated secret to our own desktop clients (one for each desktop app basically) and then during the auth process we send that key over to the top level provider that calls back to us and re-validates with us. That way we can revoke on own secrets we issue to each desktop client. (Borrowing a lot of how this works from SSL). This entire system would be prefect for value-add webservices as well that pass on calls to a third party webservice.
The process could also be done without delegation verification callbacks if the top level provider provides an API to generate and revoke new delegated secrets. Facebook is doing something similar by allowing facebook apps to allow users to create sub-apps.
There are some talks about the issue online:
http://blog.atebits.com/2009/02/fixing-oauth/
http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14
Twitter and Yammer's solution is a authentication pin solution:
https://dev.twitter.com/oauth/pin-based
https://www.yammer.com/api_oauth_security_addendum.html
With OAUth 2.0, you can store the secret on the server. Use the server to acquire an access token that you then move to the app and you can make calls from the app to the resource directly.
With OAuth 1.0 (Twitter), the secret is required to make API calls. Proxying calls through the server is the only way to ensure the secret is not compromised.
Both require some mechanism that your server component knows it is your client calling it. This tends to be done on installation and using a platform specific mechanism to get an app id of some kind in the call to your server.
(I am the editor of the OAuth 2.0 spec)
One solution could be to hard code the OAuth secret into the code, but not as a plain string. Obfuscate it in some way - split it into segments, shift characters by an offset, rotate it - do any or all of these things. A cracker can analyse your byte code and find strings, but the obfuscation code might be hard to figure out.
It's not a foolproof solution, but a cheap one.
Depending on the value of the exploit, some genius crackers can go to greater lengths to find your secret code. You need to weigh the factors - cost of previously mentioned server side solution, incentive for crackers to spend more efforts on finding your secret code, and the complexity of the obfuscation you can implement.
Do not store the secret inside the application.
You need to have a server that can be accessed by the application over https (obviously) and you store the secret on it.
When someone want to login via your mobile/desktop application, your application will simply forward the request to the server that will then append the secret and send it to the service provider. Your server can then tell your application if it was successful or not.
Then if you need to get any sensitive information from the service (facebook, google, twitter, etc), the application ask your server and your server will give it to the application only if it is correctly connected.
There is not really any option except storing it on a server. Nothing on the client side is secure.
Note
That said, this will only protect you against malicious client but not client against malicious you and not client against other malicious clients (phising)...
OAuth is a much better protocol in browser than on desktop/mobile.
There is a new extension to the Authorization Code Grant Type called Proof Key for Code Exchange (PKCE). With it, you don't need a client secret.
PKCE (RFC 7636) is a technique to secure public clients that don't use
a client secret.
It is primarily used by native and mobile apps, but the technique can
be applied to any public client as well. It requires additional
support by the authorization server, so it is only supported on
certain providers.
from https://oauth.net/2/pkce/
For more information, you can read the full RFC 7636 or this short introduction.
Here's something to think about. Google offers two methods of OAuth... for web apps, where you register the domain and generate a unique key, and for installed apps where you use the key "anonymous".
Maybe I glossed over something in the reading, but it seems that sharing your webapp's unique key with an installed app is probably more secure than using "anonymous" in the official installed apps method.
With OAuth 2.0 you can simply use the client side flow to obtain an access token and use then this access token to authenticate all further requests. Then you don't need a secret at all.
A nice description of how to implement this can be found here: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps
I don't have a ton of experience with OAuth - but doesn't every request require not only the user's access token, but an application consumer key and secret as well? So, even if somebody steals a mobile device and tries to pull data off of it, they would need an application key and secret as well to be able to actually do anything.
I always thought the intention behind OAuth was so that every Tom, Dick, and Harry that had a mashup didn't have to store your Twitter credentials in the clear. I think it solves that problem pretty well despite it's limitations. Also, it wasn't really designed with the iPhone in mind.
I agree with Felixyz. OAuth whilst better than Basic Auth, still has a long way to go to be a good solution for mobile apps. I've been playing with using OAuth to authenticate a mobile phone app to a Google App Engine app. The fact that you can't reliably manage the consumer secret on the mobile device means that the default is to use the 'anonymous' access.
The Google App Engine OAuth implementation's browser authorization step takes you to a page where it contains text like:
"The site <some-site> is requesting access to your Google Account for the product(s) listed below"
YourApp(yourapp.appspot.com) - not affiliated with Google
etc
It takes <some-site> from the domain/host name used in the callback url that you supply which can be anything on the Android if you use a custom scheme to intercept the callback.
So if you use 'anonymous' access or your consumer secret is compromised, then anyone could write a consumer that fools the user into giving access to your gae app.
The Google OAuth authorization page also does contain lots of warnings which have 3 levels of severity depending on whether you're using 'anonymous', consumer secret, or public keys.
Pretty scary stuff for the average user who isn't technically savvy. I don't expect to have a high signup completion percentage with that kind of stuff in the way.
This blog post clarifies how consumer secret's don't really work with installed apps.
http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/
Here I have answer the secure way to storing your oAuth information in mobile application
https://stackoverflow.com/a/17359809/998483
https://sites.google.com/site/greateindiaclub/mobil-apps/ios/securelystoringoauthkeysiniosapplication
Facebook doesn't implement OAuth strictly speaking (yet), but they have implemented a way for you not to embed your secret in your iPhone app: https://web.archive.org/web/20091223092924/http://wiki.developers.facebook.com/index.php/Session_Proxy
As for OAuth, yeah, the more I think about it, we are a bit stuffed. Maybe this will fix it.
None of these solutions prevent a determined hacker from sniffing packets sent from their mobile device (or emulator) to view the client secret in the http headers.
One solution could be to have a dynamic secret which is made up of a timestamp encrypted with a private 2-way encryption key & algorithm. The service then decrypts the secret and determines if the time stamp is +/- 5 minutes.
In this way, even if the secret is compromised, the hacker will only be able to use it for a maximum of 5 minutes.
I'm also trying to come up with a solution for mobile OAuth authentication, and storing secrets within the application bundle in general.
And a crazy idea just hit me: The simplest idea is to store the secret inside the binary, but obfuscated somehow, or, in other words, you store an encrypted secret. So, that means you've got to store a key to decrypt your secret, which seems to have taken us full circle. However, why not just use a key which is already in the OS, i.e. it's defined by the OS not by your application.
So, to clarify my idea is that you pick a string defined by the OS, it doesn't matter which one. Then encrypt your secret using this string as the key, and store that in your app. Then during runtime, decrypt the variable using the key, which is just an OS constant. Any hacker peeking into your binary will see an encrypted string, but no key.
Will that work?
As others have mentioned, there should be no real issue with storing the secret locally on the device.
On top of that, you can always rely on the UNIX-based security model of Android: only your application can access what you write to the file system. Just write the info to your app's default SharedPreferences object.
In order to obtain the secret, one would have to obtain root access to the Android phone.

Securing MY REST API for use with MY IOS APP only

I am designing a REST API in Laravel to be used with my ios app. Currently I am stuck on the following point: How to secure my REST API to allow access to ONLY my ios app?
I have read about HTTP Basic Authentication, HMAC, oAuth2.
1) Basic authentication requires SSL and it requires you to send the username:password on every api call.
But this doesn't stop others from using the API from other applications assuming they post their login credentials to the endpoints?
2) I understand the HMAC method and how the client & server both know of a Public & Private key. The private key is encrypted along with the request and other data. The public key is sent in the headers. When the server receives the request it detects the public key in the headers and associates it with a private key in the DB. It then recalculates the hash and checks if it matches. So, I have the following questions:
How does a newly registered user get the private key to be stored in the IOS app if the private key is not to be sent over the wire?
Is this more geared towards applications that will utilize your app? I normally see this in a API dashboard like Instagram & Facebook where they give you an app secret key, right?
3) oAuth2 - To me this seems more like allowing people to login to my app utilizing another API. For ex, allowing users to login to my app with FB and allowing my API to utilize Facebooks data? I am not really needing to do this at the moment.
am I misunderstanding this?
It sort of sounds like I need to incorporate something similar to the HMAC method by granting my IOS APP a private key where I store this in my IOS APP code. When a request is ran from within the ios app i pass along a hash with the private key and other data and then when the request is received on the server I detect if the request came from a user within the app by recalculating the hash. I have no idea if this is secure & I would assume it isn't?
What knowledge am I lacking? I am so confused at the moment that writing this question was a big struggle. I will revise it as soon as things become more clear.
1.
You're right, this doesn't prevent non-approved clients.
2.
This isn't really a way to prevent unapproved clients, it's more about verifying that a message isn't tampered with over the wire.
3.
You're understanding oAuth correctly, it's about authenticating clients to use your API in a specific way as well as limiting permissions.
It's not really possible to lock down your API so only a specific client can use it, because there's no way to verify who the client really is. Additionally, any form of authentication or verification done on the client side can eventually be be reverse engineered, and then can be sent to the server as an 'approved' client.
Something like this could be done with a token. The server sends a token the the client, the client performs some known operation on the token, such as salting and hashing, with a known salt and hash operation, then returning the token to prove that the client is a real one.
The problem is, if someone reverse engineers your client, they can determine what that operation is, and then create their own client which authenticates the same way. Any form of client side authentication isn't true security and can't be trusted.
Another way this is broken, is if someone can MiTM your request. The request could be captured and modified before it reaches the server, and there's not really any ways to prevent that from happening aside from using SSL, which can be broken with something like SSLStrip.
Any attempt to prevent a non-approved client is basically security through obscurity, since there isn't a provably secure way to do what you're asking.
The best way to protect your API isn't by limiting which clients can access it, but by making it secure already. Best practices would include forcing SSL, only send the password once and use tokens for authentication from then on, etc.