OpenIddict, from version 3.x, encrypts access tokens by default, but you can disable this functionality. If the encryption is left re-enabled, is it possible for the client to decrypt the token or how would the client or relying party verify the access token?
So far, I have both signing and encryption keys stored in Azure Key Vault, which is accessed and used by the OpenIddict server through RsaKeyVaultProvider.
Anyone who needs to verify an encrypted token, needs to first decrypt it. So if you want to use encryption, you would have to provide the decryption key to the client or API. You could also implement some kind of introspection endpoint, which would accept the encrypted JWT, verify it and return either claims or just confirmation that the JWT is valid. Any client or API could then call this endpoint to verify the token, and you would only have to provide the decryption key to one party.
Any APIs which are accessed with this JWT can also have a gateway in front of them, which would decrypt the JWE and pass just the signed JWS.
Also remember that usually the client shouldn't be concerned about the validity of the token. The client just sends the token to the API, and either gets a correct response or not.
Normally I wouldn't go with encrypted tokens, unless you have a strong need for them. If you want to hide contents of tokens from any onlookers I would go with using opaque access tokens and implementing the Phantom Token pattern.
Related
I have a web application in C# through which I'm trying to get access token for Microsoft Graph API. I'm able to get tokens through using Client secret, but don’t want to get the token by using the client secret but get the token by other means, want to get tokens without client secrets.
I'm successfully getting the tokens using secrets and have stored them in KeyVault but getting an alert for "Explicit Credentials are being used for your application/service principals", so require some alternative to get tokens.
Is there any way to get tokens without secrets. Any help would be great.
One can use ROPC oAuth grant based on username and password instead of using Client Secrets to get access tokens. Microsoft identity platform supports the OAuth 2.0 Resource Owner Password Credentials (ROPC) grant, which allows an application to sign in the user by directly handling their password. Refer, https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
Warning:
Microsoft recommends you do not use the ROPC flow. In most scenarios, more secure alternatives are available and recommended. This flow requires a very high degree of trust in the application, and carries risks which are not present in other flows. You should only use this flow when other more secure flows can't be used.
It is not a recommended way to use without client secret since due to security concerns.
If you still don't want to use client secret go with implicit grant flow which we can easily implement on the front end by maintaining SPA and passing token to the backend
For my project I'll have multiple daemon apps making calls to my API with tokens obtained by Client Secret keys. I need a way to identify which calls are coming from which clients, and I was thinking I could use the Description field that is set when adding a Client Secret Key in Azure AD administration. However I've parsed the token's entire payload, and I don't see it in there.
Is there a way to obtain that description using the token? OR is there another way to go about identifying different api users based on the secret key they're using?
No, you cannot know which key was used.
You need to register them as different client apps in Azure AD to differentiate them.
When creating a WCF service application I've implemented UserNamePassValidator for custom authentication and this works as expected.
But due to the large amount of functionality on the service, I've decoupled this into different service contracts such as a stock management service, location management service, task management service etc. and I've then exposed these on different endpoints within the same service.
This seems to work fine, however what I would prefer is to authenticate with one endpoint and have this session state maintained across all of the endpoints. At present what happens is I authenticate to one, I can then access the functionality of that service contract but if I was to connect to another endpoint it requires me to authenticate again.
My current crutch solution is to pass the ClientCredentials between forms on the client side for authenticating, and although it's using Message security so they're encrypted over the wire this is obviously not an ideal solution.
Is there a solution to first part? And if not, what's the best practice for storing user entered credentials in memory (during runtime) at the client side.
You can implement a scheme similar to WS-Federation. It is kind of Federated Security for service level.
Firstly, your Authentication endpoint should be called STS (Security
Token Service). What it does is authentication and return a security
token to the client.
Secondly, STS should be trusted by all the Service Endpoints. When
invoking the endpoints you should pass in the security token that STS
provided so that the endpoints will be able to read that token and
recognize that the token was issued by a trusted STS.
I have implemented one with Thinktecture at https://github.com/khoanguyen/Test-WS-Federation but sorry that I didn't give explanation you will need to research a little bit about WS-Federation and Thinktecture and WIF. But you should know that it is possible to do.
A lightweight solution that I am using for REST services for mobile project is below:
I set up a Authentication endpoint. That endpoint hold a DSA private/public key pair. When client is authenticated, this endpoint generate a token and sign it with DSA private key. Then I combine the signature and token together and return it as a security token to the client.
At the service endpoints, I gave them the DSA public key (from the key pair of Authentication endpoint). The DSA public key is for verifying the security tokens.
When client call the service endpoints, it attaches the security token as a Header of HTTP message. Then, the service endpoints read the header to retrieve the security token -> extract the token and the signature from the security token -> use DSA public to verify it.
The strategy for generating the token depends on your need. In my case, my token contains client's username, expiration timestamp. By using DSA, the hacker can extract all the token's data but they cannot alter it because they must have the DSA private key to sign the altered token. Our job is just keeping the private key in secret and don't leave any sensitive info (e.g password) in the token.
This is very cheap way. I don't need to access DB to verify user, just ensure got a valid security token, token's data is just for extra need, you can even generate a random token and sign it. No session state needed.
I am creating a client server communication based on Asynchronous Sockets, my client will send the username and password to the server then the server will replay whether the account is valid, so i want to secure this steps so no one could record the conversation and keep sending it to my client to achieve illegal entry to the secret data
[The Question {Simplified}] How to securely authenticate the client to the server ... ?
[NOTE] I know SSL but i cant afford paying for a certificate so i need a free alternative to provide secure communication between my client and server.
As always, the most secure password is the one, that the server doesn't know, and that is never transmitted. So what you could do is:
On the server, store the username, a random salt ("account salt") and a secure hash of the salted password ("server shared secret").
On login, in a first step let the client transmit only the username (not secret)
The server should reply with the account salt (not secret) and a randomly generated session salt (not secret). It is important, that the server generates the session salt.
On the client, salt the password with the account salt and hash it (keep this as " client shared secret"), then salt the result with the session salt and hash it again. Transmit this as an authentication token (not secret)
On the server, take the salted hash from your DB, salt it with the session salt and hash it - if this matches the authentication token, the connection is authenticated. (Client is authenticated to server)
if you want to additionaly authenticate the server to the client, you repeat the procedure: Client generates a salt, server creates token from it by salting/hashing the stored secret.
If you want to authenticate the single requests (not only the connection), salt them with the shared secret and hash them, send this as a per-request authentication field. Since in a valid login server shared secret and client shared secret are identical,both sides should come to the same result, thus verifying the authentication field.
I typically tell people that if they find themselves doing crypto themselves they are inventing security problems. :) The odds are good you're missing edge cases. I would suggest relying on something that exists already and has been heavily secured.
If you're using managed sockets, there is a version of the stream class that does crypto for you (NegotiateStream). I would suggest starting there and seeing if it can do what you need w/o you having to invent your own.
You could use a combination of public and symmetric keys in order to secure authentication.
First send a public key for the client to send his authentication data encrypted in. If the data is valid, you could then have the client generate his own public key, and have both send symmetric keys to each other via each other's public key.
Something like that should work.
I know that this was posted a few years ago, but I thought that I would add my own two cents here now. Things have changed in the last couple of year. This might help some one else.
I do not want to take anything away from Eugen, excellent work.
The best way to encrypt the traffic between your client and your server is still using SSL/TLS. You can now get free licenses from https://letsencrypt.org/.
It sounds like you already had SSL figured out, so I would plug in with the free certs that you get from the above link
Good luck,
- Andrew
We are building a RESTful API using WCF (currently .Net 3.5, but will be moving to .Net 4 soon). We have a functional framework in place, but it is currently unsecured. It will need to be accessible from .Net applications as well as iOS, Android, and web applications.
We would like to use an HMAC Authentication scheme as described here and here, but both examples seem to fall apart when describing how to validate the hash. The first example fails to describe the UserKeys object (hashtable?) and the second example is missing the GetUserKey methods on the client- and server-side.
Can anyone provide an explanation of how the "User Key"/token is generated/stored/retrieved/used in those examples or provide a better example (with source code, if possible) of how to use HMAC Authorization in a RESTful WCF service?
Edit:
After more research, we determined that we needed more of an "Authorization" technique rather than an "Authentication" technique (semantics?). We implemented Basic Authorization and secured the API behind SSL. The Basic Authorization uses the same "Authorization" header from the web Request as the HMAC Authentication scheme, but passes a username:password string encoded in Base64 instead of a token. This allowed us to custom-validate a user against our database to determine if the user is licensed for and has appropriate security rights to access the desired API method.
We're certainly open to hearing other options on how to accomplish custom username/password validation and other methods for securing the API.
Retrieving the user key is just an implementation detail you can do any way you like but on the server it is often stored in a database along with the user name.
The basic approach is real simple.
Somehow the server and the client exchange a shared key for the user to use. This can be done any way you like, including sending an old fashioned dead tree style letter. Quite often this is just the password the user entered.
When the client wants to send a request he builds the complete request and then using the secret key computes a hash over the complete message body (and optionally some of the message headers if required)
Next the client add the computed hash and his username to the message in one of the headers and sends it to the service.
The service retrieves the username from the message header and searches the private keu for that user in its own database.
Next he computes the hash over the message body (and selected headers) using the key to generate its hash.
If the hash the client sends matches the hash the server computes the server knows the message was send by the real client and was not altered in any way.
Really the only tricky part is sharing a secret key with the user and keeping that secure. That is why some services allow for generation of shared keys with a limited life time so you can give the key to a third party to temporarily work on your behalf.
Implementation for HMAC we can find at
https://github.com/cuongle/WebAPI.Hmac