I want to authenticate user from RP1 and RP2 applications against ACS and my custom STS provider. I need to know from which application RP1 or RP2 a user came from. Is it possible and how to do it?
I think it is trivial without using ACS but how to do it with ACS.
In a federation chain, an STS is theoretically only aware of its neighbors (in this case, your IdP is only aware of ACS) and therefore you can't do this. The only officially supported way to be able to do this is to register the same physical STS as two different logical identity providers in ACS (e.g. http://myidp.com/rp1 and http://myidp.com/rp2).
In practice, however, you can do this another way, though this manner is officially unsupported. The following assumes you're using WS-Federation for your custom IdP, though you can do something similar for other protocols as well. ACS encodes all the data from the original request, including the realm and reply addresses, encoded using Base64UrlEncoding in the wctx parameter of the WS-Federation response. You can decode the context in the following manner:
SignInRequestMessage message = WSFederationMessage.CreateFromUri(Request.Url);
byte[] bytes = HttpServerUtility.UrlTokenDecode(message.Context);
string decodedContext = UTF8Encoding.UTF8.GetString(bytes);
This will give you a set of name/value pairs, two of which will be rm=<realm>&ry=<reply>, which will be the realm and reply addresses of your original RP.
As I mentioned above, though, beware that this is not officially supported and that the format of this context string may change in the future.
Related
In canvas, in order to have an LTI app authenticate, the site admin has enter the JWK for the remote site. The format of a JWK is well defined:
{
"kty":"RSA",
"kid":"...",
"use":"sig",
"alg":"RS256",
"n":"u6gqiV...",
"e":"AQAB"
}
First, can we use a tool like openssl, create a key, and generate a JWK from that? Currently we are writing code to do this using jose4j but it's not even clear if that is necessary.
second, Canvas is demanding optional fields like kid, alg, and use. We guessed that use should be "sig", we made up kid: "1" and guessed alg: "RS256"
Is there a place that is accessible (ie not behind IMSGlobal's paywall) that defines what this should be? Is it standard or specific to Canvas?
We meet again- been pouring over the LTI specs for months now, and am in the mood to see if I can spare others some headaches.
You may be familiar with validation schemas in which you use an SSL tool to generate a public and private key at the same time, entangled with each other. The public key is used to sign a payload, and since the payload itself is a factor in creating the signature, it cannot be intercepted and maliciously altered without invalidating it. The recipient is given the public key, used to verify that the the payload is clean.
JWK serves the same purpose as a public key. The only difference is, a developer doesn't need to email it to the recipient app's IT team in advance. The recipient of the JWT payload can retrieve it on-demand, all it needs to know is what URI to ask. That means the keys can actually be replaced by the sender without breaking any functionality.
As I mentioned elsewhere, in a bit of a rant more appropriate for this question:
This security step is akin to getting an email from your bank, and rather than click a potentially-spam link therein, you call your bank directly to make sure the email is on the level.
Now the sender's JWKS endpoint doesn't really know ahead of time who's going to reach out to it, and may want to service multiple other entities, so it may actually supply an array of public keys to cover all bases. The recipient of course only cares about the one associated with the payload it just received, so within the JWK signaure is a "kid", that can be matched up to the 'kid' in one of those array elements, affiliated with the relevant key.
How to create a JWK? Go here. Dependencies are listed at the top, and they probably use openssl under the hood.
The JWKs is a method of exchange the public keys between the tool and the platform, and to allow each side to control the rotation of their keys. The format for a JWKs is a managed ietf standard.
LTI 1.3 is based on the OIDC third-party initiation flow, which in-turn is based ontop of OAuth2. However, a full working knowledge of these specifications is not required to integrate your application with LTI 1.3. IMS curates a collection of code examples on github that might help you get started.
All,
I am trying to mount a NAS drive to a Linux VM.
I have a requirement to encrypt the data in transit, i.e. I want data to be encrypted when
its written from the Linux to the NAS dribe
https://www.dellemc.com/hu-hu/collaterals/unauth/technical-guides-support-information/products/storage/docu88304.pdf
As per the above link krb5p provides encryption of data.
krb5p: Kerberos authentication, data integrity, and data privacy by encrypting the data before sending it over the network. Data encryption requires additional
https://www.varonis.com/blog/kerberos-authentication-explained/
I understand how Kerberos mutual-authentication works but once access is granted to the service (in my case the NAS drive) how does the data transferred to the NAS gets encrypted.
Can someone provide additional details or documentation on how "encryption" works with krb5p?
I am unable to find any additional details.
As per:
https://whyistheinternetbroken.wordpress.com/tag/krb5p/
when using krb5p:
NFS packets will be encrypted with the enctype specified in the Kerberos configuration.
But what are the available enctype that can be specified?
I have attached a diagram that tries to explain the flow of messages b/w Server-KDC-Client
Kerberos allows mutual authentication between a client and a KDC, the KDC and a service, and a client and a service. This happens by way of key agreement between each party.
Client and KDC prove knowledge of a shared key, KDC and service prove knowledge of a different shared key, so client and service can generate yet another random key and agree with one another.
In other words when the client sends the ticket to the service it contains a secret key that both parties can use to encrypt data after authentication has succeeded. In this case that key is what is used to protect NFS traffic.
What enctype is selected is somewhat undefined. It's up to all three parties to agree on one, and each has an opportunity to change it. In practice it's up to the service to make the final decision though. It should be whatever it thinks the strongest algorithm the client can handle. This usually means RC4, AES128, or AES256.
Kerberos just provides the encryption key, but it doesn't magically perform the encryption itself – that has to be done by the NFS client and NFS server themselves. They are aware that krb5p was negotiated, and will call the corresponding encryption/decryption functions when needed. (More specifically, it happens in the SunRPC layer, which NFS is built on.)
When the Kerberos KDC issues you a ticket for "nfs/yourserver.example.com", that ticket includes two copies of a randomly generated session key: one copy decryptable by you, and the other copy decryptable by that server.
The KDC will mark this session key with the best enctype that is common between what was indicated in your ticket request, and what long-term keys are held by the server's principal. Usually this will be AES256-CTS, though it can be RC4 (arcfour) if the service key hasn't been changed in a very long time.
For example,
The "nfs/yourserver.example.com" principal has long-term keys for aes256-cts-sha1-96, aes128-cts-sha1-96, arcfour-hmac, des3-cbc.
Your client making the AS_REQ indicates support for aes256-cts-sha384, aes128-cts-sha256, aes256-cts-sha1-96, aes128-cts-sha1-96.
The KDC chooses aes256-cts-sha1-96 as the best enctype for the session key.
This indication is stored in the ticket itself. If the client is using MIT Krb5 software, you can use kvno to manually request a service ticket (if you don't have one yet) and then klist -e to see the enctypes set for that ticket – "skey" indicates the enctype that the session key is meant to be used with.
So after receiving the ticket from the KDC, you send it to the NFS server as part of the RPCSEC_GSS authentication process, and now both you and the server have copies of the session key. (The same session key remains in use for as long as the service ticket is valid – usually 10 hours.)
The set of possible enctypes is:
aes256-cts-hmac-sha384-192, aes128-cts-hmac-sha256-128: New, not supported by most implementations yet (and most services won't have keys of that type yet, either).
aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96: Widely supported by all Kerberos implementations.
camellia256-cts-cmac, camellia128-cts-cmac: Decent alternatives to AES, but rarely used in practice.
arcfour-hmac (RC4): Deprecated, but still occassionally used. Gone from Linux 5.10.
des3-cbc-sha1: Deprecated, but still implemented.
des-cbc-md5, des-cbc-crc: Completely obsolete. Hope you'll never see those.
(Don't believe webpages saying that Linux NFS client only supports DES – that was fixed in 2010 for v2.6.35, and AES is fully supported now.)
My case is that I want to make the data protected even from people who have access to the back-end (the keys store), so they couldn't read it without the user's (represented by the client app, in my case the browser) assistance.
One option is to have the decryption keys stored on the client and passed with each request which sounds pretty messy to me and i'm not sure I want my keys to wander around the net like this. What I imagine though is that the client will keep some token (it might be a password the user knows) and the decryption can't happen without it.
I thought about using the purpose string for this, I have the feeling it is not a good idea since its main purpose is isolation. On the other hand it is part of the additional authenticated data used for subkey derivation. (based on this article https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/implementation/subkeyderivation?view=aspnetcore-2.1#additional-authenticated-data-and-subkey-derivation).
I came across some examples that create their own symmetric encryption with a lower level classes. (like this post Encrypt and decrypt a string in C#?). Since I'm not an expert in this area I would like to use as much build in classes as possible.
What is the recommended way to achieve what I need with the classes from the Data Protection API? (I'm using .net core 1.1 on Ubuntu)
My question is pretty simple:
If you have two web-application components:
Server-side (secret-capable) code in PHP, Python, Perl ... whatever
The javascript output and interpreted by the browser
Given a single redirection to the authorisation endpoint (and back) is it possible to specify and transfer the information for:
An authorization code grant (for the server-side code)
An implicit grant with restricted rights for the Javascript
thereby transferring the two grants (one in the request-url proper and the other in the fragment) in one round-trip without violating the RFC?
One redirect-loop seems cleaner than one for each grant (even if the second doesn't block due to previous authorization)
Thanks in advance!
References
https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-16#section-4.2
edit 1: code_and_token seems to be the type of thing I am after ... an auth code grant for the server to request the access code using its credentials ... and an implicit token for the javascript. As mov matake mentions, it was pulled from the RFC after v11, with no real note as to why. Facebook and Google seem to support this which makes me suspect it will return.
The token_and_code request type was removed from the specification because it needed significant work in terms of security analysis and rules, and no one offered to do it. It was originally proposed by a Twitter engineer who left the working group shortly after.
It will not be added to the specification, but it can easily be introduced by an extension. Google supported this flow on the list, but later said they will not implement it, and instead, will implement something else using HTML5 features.
OAuth 2.0 had "code_and_token" response type before (might be "token_and_code").
But it had been removed from the spec later.
So in current spec, if you need code for your server, the way will be
use "code" response type
get an access token on server side
and give it to the client side
You can't get scope-restricted token only for client side though..
Or you might set up an proxy on your server side for your client side code.
http://www.ietf.org/mail-archive/web/oauth/current/msg04969.html and http://www.ietf.org/mail-archive/web/oauth/current/msg03655.html
says that the "code_and_token" type was good, but the RFC didn't make it clear enough that the token in the fragment (for Javascript) should/could have less rights than the token obtained by the access code...
Thanks Nov Matake for pointing out the code_and_token type was part of the spec (at one point) as I missed it in the old specification versions (though it is widely implemented).
Looks like it will make a comeback though, as it is quite well supported by existing implementations at Google and Facebook and seems to be a core request to support both user-agent tokens and server-side access codes in one round trip.
The problem seems to be defining the semantics of "scope" in this context as well as defining a degree to which scope can differ in a single request. It makes sense that the user-agent token has limited rights, ie not the same rights as the client application.
We shall wait and see ... the downside of implementing off the back of an involving RFC.
This is related to another question I asked. In summary, I have a special case of a URL where, when a form is POSTed to it, I can't rely on cookies for authentication or to maintain the user's session, but I somehow need to know who they are, and I need to know they're logged in!
I think I came up with a solution to my problem, but it needs fleshing out. Here's what I'm thinking. I create a hidden form field called "username", and place within it the user's username, encrypted. Then, when the form POSTs, even though I don't receive any cookies from the browser, I know they're logged in because I can decrypt the hidden form field and get the username.
The major security flaw I can see is replay attacks. How do I prevent someone from getting ahold of that encrypted string, and POSTing as that user? I know I can use SSL to make it harder to steal that string, and maybe I can rotate the encryption key on a regular basis to limit the amount of time that the string is good for, but I'd really like to find a bulletproof solution. Anybody have any ideas? Does the ASP.Net ViewState prevent replay? If so, how do they do it?
Edit: I'm hoping for a solution that doesn't require anything stored in a database. Application state would be okay, except that it won't survive an IIS restart or work at all in a web farm or garden scenario. I'm accepting Chris's answer, for now, because I'm not convinced it's even possible to secure this without a database. But if someone comes up with an answer that does not involve the database, I'll accept it!
If you hash in a time-stamp along with the user name and password, you can close the window for replay attacks to within a couple of seconds. I don't know if this meets your needs, but it is at least a partial solution.
There are several good answers here and putting them all together is where the answer ultimately lies:
Block-cipher encrypt (with AES-256+) and hash (with SHA-2+) all state/nonce related information that is sent to a client. Hackers with otherwise just manipulate the data, view it to learn the patterns and circumvent everything else. Remember ... it only takes one open window.
Generate a one-time random and unique nonce per request that is sent back with the POST request. This does two things: It ensures that the POST response goes with THAT request. It also allows tracking of one-time use of a given set of get/POST pairs (preventing replay).
Use timestamps to make the nonce pool manageable. Store the time-stamp in an encrypted cookie per #1 above. Throw out any requests older than the maximum response time or session for the application (e.g., an hour).
Store a "reasonably unique" digital fingerprint of the machine making the request with the encrypted time-stamp data. This will prevent another trick wherein the attacker steals the clients cookies to perform session-hijacking. This will ensure that the request is coming back not only once but from the machine (or close enough proximity to make it virtually impossible for the attacker to copy) the form was sent to.
There are ASPNET and Java/J2EE security filter based applications that do all of the above with zero coding. Managing the nonce pool for large systems (like a stock trading company, bank or high volume secure site) is not a trivial undertaking if performance is critical. Would recommend looking at those products versus trying to program this for each web-application.
If you really don't want to store any state, I think the best you can do is limit replay attacks by using timestamps and a short expiration time. For example, server sends:
{Ts, U, HMAC({Ts, U}, Ks)}
Where Ts is the timestamp, U is the username, and Ks is the server's secret key. The user sends this back to the server, and the server validates it by recomputing the HMAC on the supplied values. If it's valid, you know when it was issued, and can choose to ignore it if it's older than, say, 5 minutes.
A good resource for this type of development is The Do's and Don'ts of Client Authentication on the Web
You could use some kind of random challenge string that's used along with the username to create the hash. If you store the challenge string on the server in a database you can then ensure that it's only used once, and only for one particular user.
In one of my apps to stop 'replay' attacks I have inserted IP information into my session object. Everytime I access the session object in code I make sure to pass the Request.UserHostAddress with it and then I compare to make sure the IPs match up. If they don't, then obviously someone other than the person made this request, so I return null. It's not the best solution but it is at least one more barrier to stop replay attacks.
Can you use memory or a database to maintain any information about the user or request at all?
If so, then on request for the form, I would include a hidden form field whose contents are a randomly generated number. Save this token to in application context or some sort of store (a database, flat file, etc.) when the request is rendered. When the form is submitted, check the application context or database to see if that randomly generated number is still valid (however you define valid - maybe it can expire after X minutes). If so, remove this token from the list of "allowed tokens".
Thus any replayed requests would include this same token which is no longer considered valid on the server.
I am new to some aspects of web programming but I was reading up on this the other day. I believe you need to use a Nonce.
(Replay attacks can easily be all about an IP/MAC spoofing, plus you're challenged on dynamic IPs )
It is not just replay you are after here, in isolation it is meaningless. Just use SSL and avoid handcrafting anything..
ASP.Net ViewState is a mess, avoid it. While PKI is heavyweight and bloated, at least it works without inventing your own security 'schemes'. So if I could, I'd use it and always go for mutual authent. Server-only authentification is quite useless.
The ViewState includes security functionality. See this article about some of the build-in security features in ASP.NET . It does validation against the server machineKey in the machine.config on the server, which ensures that each postback is valid.
Further down in the article, you also see that if you want to store values in your own hidden fields, you can use the LosFormatter class to encode the value in the same way that the ViewState uses for encryption.
private string EncodeText(string text) {
StringWriter writer = new StringWriter();
LosFormatter formatter = new LosFormatter();
formatter.Serialize(writer, text);
return writer.ToString();
}
Use https... it has replay protection built in.
If you only accept each key once (say, make the key a GUID, and then check when it comes back), that would prevent replays. Of course, if the attacker responds first, then you have a new problem...
Is this WebForms or MVC? If it's MVC you could utilize the AntiForgery token. This seems like it's similar to the approach you mention except it uses basically a GUID and sets a cookie with the guid value for that post. For more on that see Steve Sanderson's blog: http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
Another thing, have you considered checking the referrer on the postback? This is not bulletproof but it may help.