Identity Server Authenticate without password - security

We have a customer facing API where we give API Keys that map back to users. Once we look up the userName via API Key we then need to get a JWT from identity server. How can this be done without supplying the password?

This sounds like a job for a custom grant type. Another option is to issue long lived reference tokens which effectively become the API key.

Related

Active Directory B2C authentication and making/storing user IDs in a DB

I'm making a mobile app and want to use the AD B2C stuff to handle authentication for my users. I need to store data for them in a SQL DB which will also be on Azure. I intended to have my app use REST to communicate with some Functions I was going to write to then talk to the DB back end which would query various things specific to that user. My problem is I'm not sure how to map a user who has been authenticated with the authentication system to some unique ID or index in my DB. Is there some way that I can safely identify a newly registered or logged in user such that I can create a way of identifying them? I say safe because I don't want to commit a faux pas and use some value from the auth library that would be considered a security risk or bad practice. Thanks.
In the auth token you receive back from Azure AD, you have an object ID that is unique to each user.
The B2C token is slightly different to the regular AD token, you don't get back all the values listed in the Token Reference (e.g. Groups, you have to query for these separately), but you will get the object ID that you can then use to lookup your DB.
https://azure.microsoft.com/en-gb/documentation/articles/active-directory-token-and-claims/
You can decode your JWT token here to see what you get back: https://jwt.io/

azure media service aes jwt token

I use azure media player with aes content protection.
Login our server get token, but that set token in html or javascript.
If our user copy the token and paste to himself html page.
My content protection will return the key.
Any way to limit one token one user?
Thanks a lot.
you can check http://gtrifonov.com/2015/01/24/mvc-owin-azure-media-services-ad-integration/ to get idea how to restrict video playback based on jwt token user group claims. Technically you can create restrictions by checking any claim in a token. For example user email or id. But you need to configure these restrictions for video using sdks.
Some unit tests can be found here https://github.com/Azure/azure-sdk-for-media-services/blob/d543e77ec47691110575078e8df71c55c2d7128e/test/net/unit/TokenRestrictionTemplateSerializerTests.cs.
Code below for example will create restriction that only users which token contains claim 'Rental' will be able to get key.
TokenRestrictionTemplate template = new TokenRestrictionTemplate(TokenType.JWT);
template.Audience = _sampleAudience;
template.Issuer = _sampleIssuer;
template.RequiredClaims.Add(new TokenClaim("Rental", "true"));
try
{
TokenRestrictionTemplateSerializer.Serialize(template);
}
If you using Azure AD you can find list of supported claims here https://azure.microsoft.com/en-us/documentation/articles/active-directory-token-and-claims/.
For example you can use claim "unique_name" to check.
In practice you would probably will go with security group claims since it is easy to manage compare to granting permissions to individual user names.
Nothing stop authenticated user to copy token and mitigate this you can do following:
Switch to DRM protection like PlayReady and Widewine. More protection and restriction options
Minimize token lifetime by crafting your own token instead of using user session tokens from Active Directory or other providers. You need to have some mechanism to request token right before user actually plays video. Content key retrieval need to be performed once to decrypt playback, so if two events are close together you are minimizing possibility of reusing same token.
You can create proxy which retrieves content key based on custom logic - for example to serve content key only once. And use you proxy as endpoint for content keys.
You could set the expiry time to less than 5 minutes - so the token expires in a short period of time, just enough for user to retrieve the key. Therefore, so when user passes the token to another, the token wont be useful anymore (probably expired). As said, what you mentioned is one-time token, which we don't support today.

Method for storing users passwords for other services

I run a service that integrates with a few other cloud platforms via their apis. In order to do this, we have to store the login credentials for OTHER sites in our database. Obviously security is a bit of a risk here.
So far, we have been storing the passwords using AES encryption and a salted version of the user's password(for our site) as the cipher. When a user requests something from the api, they must input their password. The password checked for validity against the sha hash that we store, and once confirmed, is used to decrypt the password.
The problem is, we would like to start offering a service that retrieves data from the apis we interact with at scheduled intervals(outside the scope of synchronous user requests.). If we do this, our current security structure will no longer be viable.
My question is, are there any ways to allow for this type of api interaction without storing recoverable versions the passwords in our database? If not, what are my options for securely storing passwords?
we would like to start offering a service that retrieves data from the apis we interact with at scheduled intervals(outside the scope of synchronous user requests.).
This is what the OAuth protocol is designed for. The OAuth 2.0 code grant gives a client application an access token and a refresh token. The refresh token allows the application to get an access token even when the user is not there to authorize the request.

How can private data be secured with OAuth2 authentication?

I am setting up a website to use Google's OAuth2 interface for user authentication. The website will store private data associated with each user - which I'm planning to encrypt.
If I implemented my own authentication method for the website, I could easily derive a key from the user's credentials (which include the user's password), allowing the data for each user to be strongly protected. But with OAuth2, I believe I can only receive an access token, granting that user permission for a period of time - the problem is that the access token value will change over time.
Is there a way that OAuth2 can provide me with an immutable secret tied to the user which I can use to derive a secure key from? Or is there some other method of creating a secure persistent secret using OAuth2?
--- Edit ---
In response to the questions and comments, here are some thoughts to consider:
All user information should always be protected with strong encryption and user authentication - the reason we read so many news articles about website & database hacks is because developers say "do we really need to secure that" and then respond with "No - because no-one but us will be able to access the database, security is hard, etc". The hacker downloads the database et violá. Credit cards, email addresses, phone numbers, passwords, you name it, then become compromised.
There are only two real secrets - one is a password stored in someone's head, the other is a strong random value that only the authorised user has access to (like a physical token). If you think a secure key can be derived from an email address alone, or that a secret needs to be stored in a database, you don't really understand security.
I guess what I was trying to discover was whether an OAuth provider can provide to the OAuth client an immutable value securely linked to both user and client - effectively, this would be a key that could only be unlocked by the OAuth provider using a combination of the user's secret (their authentication password) and the client's secret (used in the OAuth protocol). The client could then use this value to provide a reasonable level of security for the user's data.
Of course this implementation is not perfect from abuse, but implemented correctly, could provide a reasonable way to secure data whilst still using the good practices of the OAuth scheme.
The point of the token is that you can then use the token to obtain information from Google about the user. During the initial authentication, you will tell the user, and google, that you want to access certain information about the user:
https://developers.google.com/+/api/oauth
Assuming that the user allows you to access their information, such as their email address, you can then get their email address from google. Once you have their email address, you can generate a secret key for their user, store this in your user table, and use it to encrypt their data. Then, when they login again, you can lookup their email address and find their key.
Is there a specific need for the immutable information be 'secret'? Or is it just a key to identify a user?
If the information that you're storing is truly private, and you want to make it so that you can't access your user's data, then all you have to do is store the encrypted blob for your users. Once the user had downloaded their data, they can use their key to decrypt the data client-side.
My first question would be: Why do you want to derive your encryption keys from some tokens?
The tokens and your encryption keys could remain independent and can be associated to a user identified by a unique id. User authentication can be done by whatever way you need either via credentials or open ID authentication or something else. But, once a user is authenticated, your decryption APIs can fetch the decryption key associated with the authenticated user and do whatever decryption it has to.
This way you can potentially allow users to tie multiple open ID accounts with the same user similar to what Stackoverflow does. I can associate my yahoo, facebook and google accounts with my Stackoverflow user and can sign in with any of those providers. I can disassociate those accounts any time I want. But that does not affect my Stackoverflow profile and data.
So, it is not a good idea to derive your keys from something that is not constant and keeps changing. Instead, keep them separate.
If I implemented my own authentication method for the website, I could easily derive a key from the user's credentials
This schema has a terrible weakness - if a user forgets /resets its credentials, the key is lost forever
Is there a way that OAuth2 can provide me with an immutable secret tied to the user which I can use to derive a secure key from?
OAuth2 is an authorization protocol. It is not intended to give you any user secrets.
the Google's OAuth2 should provide a user info service returning username (email) and some id (sub).
However these are identity information, not any secrets. And mixing user credentials is imho bad idea (as already mentioned), using an external IdP (google) you will have no access to credentials tat all.
And now what?
My suggestion:
If you really want to encrypt user's data using a user-provided secret, let the user provide the secret or encrypt the data encryption key by the user itself (or using user's public key?). The user must be aware that if this secret is lost, the data will be unaccessible. It is quiet uncomfortable in long run. Some DMS systems use this approach to encrypt the stored sensitive documents.
if you want to encrypt data in rest (on the server, database), you may have an application specific key, imho best stored somewhere else (key vault, key management service,..). Indeed then there is a different risk profile (you have to protect the key,..) but it's much more convient for users. This is usually good enough along other security measures (even big enterprises don't ask for a separate password to encrypt your credit card number or email)
What you need is constant secure (random) key for each user that you could get from authentication service that gives OAuth2 endpoint (in this case - Google).
OAuth2 protocol itself does not provide such value - Authentication server uses generated values that are not constant. But OAuth2 does not prohibit from giving this value from Resource server (together with user id, email etc). So basically OAuth2 lets you secure data in the way you want, but Google, which you currently use, does not give this type of constant random value.
Also note, that this would not work if you would let user relate few accounts, like Google and Facebook, as they would give different random keys.
If you derive secret from credentials, this would also mean that resetting password would reset user account.
Furthermore, if you encrypt data like emails in this way, it becomes impossible to decrypt them without currently signed-in user. So emailing newsletter becomes practically impossible. You cannot query the data in SQL also.
I could only suggest some countermeasures:
Do not store sensitive data at all, or store it hashed. Passwords must be hashed, not encrypted. Do not store CC numbers, store tokens that represent them.
Use encryption with key, stored in another data source. This adds at least some security - attacker must get not only DB copy, but also encryption key.
As data is encrypted, storing it in database is no longer necessary. You can store encrypted data in files or some other source, where it is safer than in DB (no risk of SQL injections etc)
I've been having this same issue. So far, I can't find a secure way around it.
Basically, we need a per-site randomly generated secret provided only with implicit flow that can be used to derive credentials to access systems and decrypt data.
Because I want to protect the data from myself, I could write the client to salt/hash the secret in two ways, one way to retrieve the data and another to decrypt it.
Alas, this is not the case.
I could derive credentials from things in the basic scope of the oAuth and that would protect the data against me, but that leaves the user wide open for cross-site vulnerabilities, and besides, personally identifiable information makes for a poor secret.
The best I got is to use implicit flow oAuth2 to acquire the user's email address, randomly generate a client side secret, and force the user to email themselves the secret (as a recovery key), then store the secret in localStorage. Salt/Hash the secret + oauth scope variable to derive the credentials client side (so the user must be logged in) needed to access, encrypt and decrypt data.
If the user ever clears their localStorage, they need to go click the link in the recovery email, which places the secret back into localStorage.
This places the scope of vulnerability back on the client, but is resistant to public machines (would have to know who was logged in last, and get access to the localStorage token), allows for recovery, and weakly requires the user to be logged in. Still vulnerable to plugin injection attacks and physical access + knowing the user.
Update: I have decided to use some oAuth extensions (hello.js, folder APIs) to store the keys in the user account as files. It requires some permissions and some APIs to implement, but appears to be viable.

How can we support ADFS if we *require* a shared secret for encryption?

EDIT: (summary): I'm looking first for a way to have a custom, user-specific attribute passed to us as part of the ADFS signon; if that's reasonable, I'll dig into how to secure it.
EDIT: (clarification): I don't want to pass something through AD at time of login -- if the user has to enter their password and then authenticate again against AD, they're going to end up with confusing, mis-matching passwords. Instead I want registration with us to go like this:
user enters details (email, etc)
we generate a long random string, encrypt it, then provide that as part of a unique id to the client's AD
Then at each login:
We redirect the user to the client's AD for auth
Once the user is authorized, they're redirected back to us with user & claim info
That info includes the unique ID we generated -- so we extract a user ID and decrypt the password from that.
This would be lower security than we normally offer, but it's the best I can imagine if AD is involved. Is this possible?
Long version: A customer is asking that we add support for single sign-on to our web application, implementing Microsoft ADFS (Active Directory Federated Services).
The problem is that we rely on the user's password to decrypt their record; their private key is encrypted with their password, so we can't access their record without the password.
I've been digging into the documentation, e.g., http://msdn.microsoft.com/en-us/library/bb897402.aspx -- but currently I don't see way to securely manage some kind of secret encryption key using AD FS.
It wouldn't have to be the password itself, of course -- we implemented OAuth2 by generating random access tokens that have the same properties as a password (can be used to decrypt the user's record)... but an incoming, authenticated user needs to come with some kind of secure, private token.
Any guidance much appreciated!
If you are using ADFS 2.0, you can customize the pages.
So you could e.g. take the password, mangle it, write it to AD before invoking the SignIn and then have a claims rule that passes this. Then reverse the process in your application.
Note - I'm not suggesting that this is a "good" solution - just an example of what you can do.
Obviously security needs to be paramount!
Well there is Two ways to get your problem solved.
Customize the ADFS SignOn page(you should anyways take a backup) to create a form that receives users password. It is an webforms aspx page so you should have no trouble doing it. From there you must build your own STS to issue claims to ADFS so that ADFS can in turn pass these to your relying party. Map the custom STS as attribute store to the ADFS
You are just doing things wrong by taking security in your hand. ADFS uses HTTPS for transport level security and secure encryption with SAML 2.0 to handle your information, so another encryption would be no-brainer.
let me know which way you like going

Resources