I'm trying to use the jwt-1.0 feature in Open Liberty.
The JwtBuilder API is pretty nice and allows to set expiration, sign, encrypt and build a token programmatically (and everything else needed).
JwtBuilder.create().expirationTime(expTime).signWith(signAlg, privateKey).encryptWith(keyMgmtAlg, keyMgmtKey, contentEncAlg).buildJwt().compact();
But the JwtConsuer API seems pretty lame and only allows to read a token without validation at all.
JwtConsumer.create().createJwt(token);
Signature validation and decryption should be configured through the application server configuration (via "jwtConsumer" and "keystore" entries) but it's not possible programmatically.
I should accommodate with this but other validations like expiration date are not possible.
Do I miss something?
You're correct in that the JwtConsumer API does not provide a programmatic way to set specific validation requirements. However the JWT will still be validated when createJwt() is called.
The JwtConsumer API's create() and create(String consumerConfigId) methods tie the JwtConsumer object to a <jwtConsumer> element in the server configuration that specifies the validation requirements. The configuration settings for that element can be viewed here: https://openliberty.io/docs/22.0.0.4/reference/config/jwtConsumer.html.
The JwtConsumer.create() method will use the default <jwtConsumer> configuration that is provided automatically by the runtime, which simply looks like this:
<jwtConsumer id="defaultJwtConsumer" />
Similarly, the JwtConsumer.create(String consumerConfigId) would use the configuration with the corresponding ID. So JwtConsumer.create("myJwtConsumer") would use the corresponding "myJwtConsumer" configuration in the server.xml. That could look something like this:
<jwtConsumer id="myJwtConsumer"
issuer="https://example.com"
audiences="Luke, Leia, Han"
signatureAlgorithm="RS256"
jwkEnabled="true"
jwkEndpointUrl="https://..."
/>
You'd put whatever validation settings you want in that configuration. Then when you call JwtConsumer.createJwt(token), the runtime will perform several validation checks against the JWT. That includes checking the issuer, audiences, iat and exp times, the nbf claim, and of course the signature of the token.
To expand on the answer, if a clockSkew is not specified, then a default value of 5 minutes is used. On the other hand, setting clockSkew="0m" will in effect disable the clock skew.
Related
In the Kubernetes docs there is a bootstrap token which is used for Nodes TLS bootstrapping.
Wherever it is mentioned there is always the same value of 07401b.f395accd246ae52d. I haven't found much details on if that numeric sequence have some special meaning and should be precisely the same for every bootstrapped Node.
Or is that just a randomly generated magic number?
That sequence carries no special meaning. The bootstrap token is entirely random. I suspect the times that specific sequence is mentioned in documentation, it's coming from or directly copied from the same source.
Bootstrap Tokens take the form of abcdef.0123456789abcdef. More
formally, they must match the regular expression
[a-z0-9]{6}.[a-z0-9]{16}.
The first part of the token is the “Token ID” and is considered public
information. It is used when referring to a token without leaking the
secret part used for authentication. The second part is the “Token
Secret” and should only be shared with trusted parties.
https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/#token-format
If you want to test this, play around with kubeadm's token create. This will generate random tokens you can use to bootstrap nodes.
kubeadm token create
Synopsis This command will create a bootstrap
token for you. You can specify the usages for this token, the “time to
live” and an optional human friendly description.
The [token] is the actual token to write. This should be a securely
generated random token of the form “[a-z0-9]{6}.[a-z0-9]{16}“. If no
[token] is given, kubeadm will generate a random token instead.
https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-token/#cmd-token-create
I have the resource /contracts with the following structure:
{
name: "Contract name",
signedAt: 123213231,
// etc.
}
While basic CRUD operations are well clear (GET /contracts, GET /contracts/{id}, POST /contracts, etc.) some doubts come when I have to do some concrete actions on the resource.
One of these actions is the following:
sign: means the contract is signed, so the signedAt date will need to be updated with the moment (date-time) the contract was signed.
So far I've been thinking about these different approaches:
PATCH-ing the resource
This approach will mean having the following endpoint method:
PATCH /contracts/{id}
and just posting the signedAt date { signedAt: 123213231 } meaning that after this the contract will be signed.
What I don't like about this approach is that the signature date comes from the client, I was thinking that having this date initialized on the backend side whenever a contract is signed could be better and more consistent.
Totally discarded, as the signedAt date should be set on the server
side exactly at the moment the sign is done.
POST-ing a new resource
This approach will mean having the signature action as a resource:
POST /contracts/{id}/sign
with an empty body in this case as we don't need to pass anything else so, once it is posted, the backend side would be the responsible for having the signature date initialized.
POST-ing the resource using 'action'
Similar to the previous approach, in this case I would use a query parameter called action on the contract resource:
POST /contracts/{idContract}?action=sign
also with an empty body where ?action=sign. Like in the previous approach, once posted the backend side would be the responsible for having the signature date initialized.
Questions
What would be the proper way to have this designed at a REST API level?
Is any of the approaches above close to a good design or not?
Would I need to modify any of the approaches?
Is there any better alternative?
I have designed a few rest APIs myself but I am not a restful evangelist so my answer might not be the best. I would suggest some of the following:
Create a custom converter for date values in your rest service that accepts date AND other specific fields. If you checkGoogle reporting APIs for example they allow you to use specific date range and also CURRENT_WEEK, CURRENT_MONTH etc. So you can add such specific value and use it. For example PATCH signedAt=CURRENT_DATE and the API handles that properly.
Add a boolean signed field to the resource. Do a POST or PATCH with signed=true. This way you will be able to eventually query only signed resources easily ;) Also it might be the case that people care only about if it is signed than when it was signed
I wouldn't use ?action=sign or /contracts/{id}/sign because these are not RESTFUL and even if you do use GET and POST you would use them in a way to create a workaround in order to implement actions in your design which shouldn't have actions
just posting the signedAt date { signedAt: 123213231 } meaning that after this the contract will be signed.
On HTTP Patch
The set of changes is represented in a format called a "patch document" identified by a media type.
Rather than rolling your own bespoke media type, you might want to consider whether one of the standard formats is suitable.
For example: JSON Patch.
Content-Type: application/json-patch+json
[ { "op": "replace", "path": "signedAt", "value": 123213231 }
JSON Merge Patch is another reasonable option
Content-Type: application/merge-patch+json
{ signedAt: 123213231 }
From what I can see, the primary difference is that JSON Patch provides a test operation which gives you finer grain control than simply relying upon validators
But you are absolutely right - PATCH gives the client code authority to specify the time value. If that's not appropriate for your use case, then PATCH is the wrong tool in the box.
POST /contracts/{id}/sign
POST /contracts/{idContract}?action=sign
As far as REST/HTTP are concerned, these two choices are equivalent -- you are updating the state of one resource by sending an unsafe request to a different resource. There are some mild differences in how these spellings act when resolving references, but as request-targets, it doesn't make a difference to the client.
An option that you seem to have overlooked:
POST /contracts/{id}
action=sign
This has the advantage that, when successful, you get cache invalidation for free.
In a hypermedia API, the flow might go something like this: the client would GET the resource; because the resource hasn't been signed yet, the representation could include a form, with a "sign" button on it. The action on the form would be /contracts/{id}. The consumer "signs" the contract by submitting the form -- the agent gathers up the information described by the form, encodes it into the request body, and then posts the request to the server. The server responds success, and the client's cache knows to invalidate the previously fetched copy of the resource.
I have a need to pass data from one system to another, during SSO using PingFederate.
Currently my link looks like this:
https://pingfederate.myexample.org/startSSO.ping?TargetResource=https%3A%2F%2Fwebapp.othercompany.org%3FkeepParam%3DkeepThisOnURLparamOne%3DvalueOne%26paramTwo%3DvalueTwo
TargetResource, decoded, looks like this:
https://webapp.othercompany.org?
keepParam=keepThisOnURL
¶mOne=valueOne
¶mTwo=valueTwo
After pingfederate processes the request, it ends up making a post to othercompany, copying the entire TargetResource into RelayState, params and all:
POST https://sso.othercompany.org
SAMLResponse: {paramOne: valueOne; paramTwo: valueTwo} //(in actual saml format)
RelayState: https://webapp.othercompany.org?keepParam=keepThisOnURL¶mOne=valueOne¶mTwo=valueTwo
My goal is to pass paramOne and paramTwo into SAML attributes somehow, but NOT carry those params over onto RelayState, keeping only keepParam=keepThisOnURL:
POST https://sso.othercompany.org
SAMLResponse: {paramOne: valueOne; paramTwo: valueTwo} //(in actual saml format)
RelayState: https://webapp.othercompany.org?keepParam=keepThisOnURL
Is this possible to do with PingFederate?
E.g., is there any other way to pass data into startSSO.ping from a browser request besides sneaking them into TargetResource?
Or if they can only be appended to TargetResource, can the value be modified (strip off most params) before copying into RelayState?
The reason that the parameters were tacked into the Relay State is because you URLEncoded them, So PingFed thought they were just part of the TargetResource.
Instead, you would do something like this:
https://pingfederate.myexample.org/idp/startSSO.ping?
paramOne=valueOne&
paramTwo=valueTwo&
TargetResource=https%3A%2F%2Fwebapp.othercompany.org%3FkeepParam%3DkeepThisOnURL
I should point out two things, the first being a showstopper:
fulfilling attributes via parameters passed in the startSSO.ping calls is not supported and won't work properly until at least one of two current feature requests are fulfilled, PPQ-1141 and PPQ-2815. Neither of these are currently scheduled (low request volume) in the development trains, so if this is critical to your work, get in touch with your Ping account executive to have your needs communicated.
I should point out that this overall methodology probably doesn't make a whole lot of sense from an operational standpoint, simply because it means that you will be dependent on an IdP initiated transaction because you have no way of fulfilling this with an SP-initiated transaction.
Based on those, I would recommend trying to architect another solution by which you could set those attributes, which I recognize may be difficult - especially if they are only derived at runtime, rather than via query to a datastore.
Using PING as my identity provider do I have an option to set multiple audience values (in the service provider configuration I add for my application) so they will be returned within AudienceRestriction element of the SAML assertion?
As I see PING adds issuer value as audience and nothing else.
Example condition element
<ns2:Conditions NotBefore="2011-01-10T20:52:56Z" NotOnOrAfter="2011-01-10T20:54:56Z">
<ns2:AudienceRestriction>
<ns2:Audience>urn:saml2:partnerspid</ns2:Audience>
</ns2:AudienceRestriction>
<ns2:AudienceRestriction>
<ns2:Audience>Audience-IDP</ns2:Audience>
</ns2:AudienceRestriction>
</ns2:Conditions>
You'll have to be running PingFed 8.0+ for this to work, which is where Ping began allowing the customization of request and response XML. You should read more on that subject in their documentation.
Using this:
#AssertionType.getConditions().addNewAudienceRestriction().addAudience("whatever:eh")
will give you something like the following element:
<saml:Conditions NotBefore="2017-03-24T20:23:55.341Z" NotOnOrAfter="2017-03-24T20:38:55.341Z">
<saml:AudienceRestriction>
<saml:Audience>pingfederate:default:entityId</saml:Audience>
</saml:AudienceRestriction>
<saml:AudienceRestriction>
<saml:Audience>whatever:eh</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
However, SAML spec (SAML-CORE-2.0, 2.5.1.4) states:
Note that multiple elements MAY be included in a
single assertion, and each MUST be evaluated independently. The effect
of this requirement and the preceding definition is that within a
given condition, the audiences form a disjunction (an "OR") while
multiple conditions form a conjunction (an "AND").
So, in that format that you are talking about, you will get an "AND". It's highly unlikely that your partner will be able to fulfill both, so I think you may be looking for an "OR". If that's the case, you'll want to use the following:
#AssertionType.getConditions().getAudienceRestrictionArray(0).addAudience("whatever:eh")
Which should produce something like:
<saml:Conditions NotBefore="2017-03-24T20:20:37.046Z" NotOnOrAfter="2017-03-24T20:35:37.046Z">
<saml:AudienceRestriction>
<saml:Audience>pingfederate:default:entityId</saml:Audience>
<saml:Audience>whatever:eh</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
I am trying to redirect all traffic for one domain to another. Rather than running a server specifically for this job I was trying to use AWS API Gateway with lambda to perform the redirect.
I have this working ok for the root path "/" but any requests for sub-paths e.g. /a are not handled. Is there a way to define a "catch all" resource or wildcard path handler?
As of last week, API Gateway now supports what they call “Catch-all Path Variables”.
Full details and a walk-through here: API Gateway Update – New Features Simplify API Development
You can create a resource with path like /{thepath+}. Plus sign is important.
Then in your lambda function you can access the value with both
event.path - always contains the full path
or event.pathParameters.thepath - contains the part defined by you. Other possible use case: define resource like /images/{imagepath+} to only match pathes with certain prefix. The variable will contain only the subpath.
You can debug all the values passed to your function with: JSON.stringify(event)
Full documentation
Update: As of last week, API Gateway now supports what they call “Catch-all Path Variables”. See API Gateway Update – New Features Simplify API Development.
You will need to create a resource for each level unfortunately. The reason for this is API Gateway allows you to access those params via an object.
For example: method.request.path.XXXX
So if you did just /{param} you could access that with: method.request.path.param but if you had a nested path (params with slashes), it wouldn't work. You'd also get a 404 for the entire request.
If method.request.path.param was an array instead...then it could get params by position when not named. For example method.request.path.param[] ...Named params could even be handled under there, but accessing them wouldn't really be easy. It would require using something some sort of JSON path mapping (think like what you can do with their mapping templates). Sadly this is not how it's handled in API Gateway.
I think it's ok though because this might make configuring API Gateway even more complex. However, it does also limit API Gateway and to handle this situation you will ultimately end up with a more confusing configuration anyway.
So, you can go the long way here. Create the same method for multiple resources and do something like: /{1}/{2}/{3}/{4}/{5}/{6}/{7} and so on. Then you can handle each path parameter level if need be.
IF the number of parameters is always the same, then you're a bit luckier and only need to set up a bunch of resources, but one method at the end.
source: https://forums.aws.amazon.com/thread.jspa?messageID=689700򨘤
Related to HTTPAPI that AWS introduced recently, $default is used a wildcard for catching all routes that don't match a defined pattern.
For more details, refer to: aws blogs
You can create a resource with path variable /{param}, and you can treat this as wildcard path handler.
Thanks,
- Ka Hou