Authenticate the JWT using firebase by using Istio endpoint authentication - kubernetes-ingress

I have a GKE Backend with GLCB(using Ingress-GCP, routing done based on path to various bakend service). My need is to verify the token in the header and pass the request to the backend iff it is valid token. And to check the validity of token i need to pass to the firebase. Once firebase say's OK then route to the correct backend.
I was initially using ingress-GCE but seems this can be only achieved by using Istio. Can any one suggest how to do istio based end user authentication ?

You can use AuthorizationPolicy and RequestAuthentication to do this. There is example about that in istio documentation.
What Istio does in the RequestAuthentication ?
As mentioned here
RequestAuthentication defines what request authentication methods are supported by a workload. If will reject a request if the request contains invalid authentication information, based on the configured authentication rules. A request that does not contain any authentication credentials will be accepted but will not have any authenticated identity. To restrict access to authenticated requests only, this should be accompanied by an authorization rule.
As mentioned here
issuer -> Identifies the issuer that issued the JWT. See issuer A JWT with different iss claim will be rejected.
Example: https://foobar.auth0.com Example: 1234567-compute#developer.gserviceaccount.com
jwksUri -> URL of the provider’s public key set to validate signature of the JWT. See OpenID Discovery.
Example: https://www.googleapis.com/oauth2/v1/certs
There are 2 examples of jwtRules and jwskUri for firebase.
https://github.com/envoyproxy/envoy/issues/5702
https://discuss.istio.io/t/istio-authentication-with-firebase/468/6
Additionall resources:
https://cloud.google.com/solutions/authenticating-cloud-run-on-gke-end-users-using-istio-and-identity-platform

Related

RapidMiner : Can't get JWT Token

I am refering below document to get JWT Token .
However when I call the API /api/rest/tokenservice it doesn't return the token but returns a web interface asking for login . How can I get JWT Token
REST API Url :
https://docs.rapidminer.com/9.10/hub/rest-api/index.html
Response of postman:
In order to query the internal tokenservice endpoint, you need a valid "session". In the native installation method, you can use basic auth as "session" as outlined in the documentation.
curl -u user:pass "http://localhost:8080/api/rest/tokenservice"
{
"idToken": "the-valid-token",
"expirationDate": "the-exp"
}
However, for this to work when you've deployed RapidMiner AI Hub with Keycloak (and docker), you need to 1. enable basic auth for Keycloak, 2. access the route by first having a valid "login session" (cookie name is RM_SERVER_JSESSIONID) or 3. use a valid Keycloak token.
Enable basic auth in Keycloak
rm-server-homedir/configuration/keycloak/keycloak.json
{
...
"enable-basic-auth": true,
...
}
Valid cookie value
Login via web interface, open the browser's developer tools and use the very same RM_SERVER_JSESSIONID cookie value inside the REST request issued to the /api/rest/tokenservice endpoint.
Not sure what you like to achieve, e.g. schedule a process via REST, I like to outline that you can easily add a process and trigger via Web Service. The triggered process could make use of the Admin Tools extension. You still need to enable Keycloak's basic auth though if you like to trigger it from "outside". A guide how to use the extension can be found here.
Valid Keycloak token
Retrieve a valid Keycloak access token (from Keycloak's token endpoint, e.g. via OpenID Connect) and query the
/api/rest/tokenservice endpoint with Authorization: Bearer .
Disclaimer: This answer is used with permission of the original author from the RapidMiner community.

Livetime for JWT tokens issued by CAS Server

It looks like CAS can issue JWT Token after login:
https://apereo.github.io/cas/5.1.x/installation/Configure-ServiceTicket-JWT.html
I have two questions about this functionality:
It is possible to configure live time (expiration) for JWT Tokens ?
It is possible to refresh such tokens on backend (using refresh token)?
The expiration time of the generated JWT is controlled by the length of the assertion returned as part of the validation event. If the assertion validity length is not specified, then the expiration time is controlled by the length of the SSO session defined as part of SSO expiration policy of the CAS server.
Not OpenID Connect
Remember that you are just receiving a ticket in form of a JWT, thereby removing the need from your client to validate a normal service ticket. The ticket is internally validated by CAS and you as the client are only left in charge of validating the JWT itself. Do not confuse this with OpenID Connect. While a JWT, the token itself is not an ID token, cannot be refreshed and must be obtained again once you deem it expired. If you need more, consider using the OpenID Connect protocol instead.

Is it ok to store user credentials in the JWT

Is it ok to store user credentials (username / password) in the JWT (so sign it and verify the resulted token later)?
I heard that
No, it is not secure to send a password in a JWT. This is because the
JWT claims are simply encoded and can easily be decoded by anyone that
sees them. It is not secure to store any sensitive information in a
JWT that returned to a user
but I don't know why does the JWT website recommends using it for authentication purposes then:
When should you use JSON Web Tokens?
Here are some scenarios where JSON Web Tokens are useful:
Authentication: This is the most common scenario for using JWT. Once
the user is logged in, each subsequent request will include the JWT,
allowing the user to access routes, services, and resources that are
permitted with that token. Single Sign On is a feature that widely
uses JWT nowadays, because of its small overhead and its ability to be
easily used across different domains
The JWT is the result of the authentication. For example
User sends his credentials (e.g. username/password) to an authentication service. It could be a third party one or one inside your monolith or your own microservices dedicated to authentication.
The service validates username-password. If authentication success it returns an JWT that represents that the user is already authenticated, in other words he is who claim he is. This JWT could contain a payload without sensitive information (don't store the password here).
The user sends another request to a service business with the JWT. If the JWT isn't expired and is not corrupted (the sign is still valid) then the service could trust in its JWT. Maybe this task will be delegated to an authorization service.
What is inside the JWT token?
Well, the simplest JWT contains information about the sign (I can't enter in much detail here because I'm not a security expert) that allows to check if the sign has been corrupted when a request with the JWT is received.
This information can be verified and trusted because it is digitally signed
Besides that, the JWT allows to send a payload.
More formally, the JWT is composed by:
Header: type of the token + hashing algorithm being used
Payload: Claims are statements about an entity (typically, the user) and additional metadata.
Signature: The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
For example, if I send a request to a authentication service with my credentials username:password being gabriel:giussi, it will check these credentials and if they're OK it could create the following JWT:
Then with every request I will then the encoded JWT that contains my username and the service will
Perform authorization (What Gabriel is authorized to do?) if the JWT sign is valid.
Ask me to login again if the JWT has expired
Return an authentication error if the sign is broken.
Shortly: yes, it is OK to pass/receive sensitive data in JWT if you encrypt the data before placing into JWT's payload and decrypt it after the JWT validation to use it.
In a general case you would not need to keep user credentials in the JWT because the JWT is by itself a dynamically generated credential that represents the login / password (or the other means of authentication) provided at the JWT's first generation time.
1.1 You could however pass something that is not as sensitive as pure login / password but still bears the valuable information you need at the JWT validation time. It can be user ID (in a sub claim, hashed if desired), or access level code or the like.
Nevertheless if you wish you can pass the sensitive information with JWT. And this is all pretty easy as per below.
2.1 For sensitive data you could use your specific private claims in the JWT's payload, e.g.:
{
// These are registered claims: (see https://www.rfc-editor.org/rfc/rfc7519#section-4.1)
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
// There can be some public claims you are not afraid to expose to the world
// these are omitted here for brevity (see https://www.rfc-editor.org/rfc/rfc7519#section-4.2).
"omitted": "for brevity",
// And here can go some private claims you wish to include in the payload, e.g.:
"sensitiveInfo": {
"username": "admin",
"password": "12345",
"account_balance": 10000,
"etc": "something else"
}
}
2.2 The sensitiveInfo payload key by default is only base64-encoded (so it is easily read by anyone who gets the JWT). To make it secure you can encrypt it with some external module (e.g. crypto or bcrypt on NodeJS or PHP's techniques of your choice).
2.3 In this case:
At the JWT generation step you have to encrypt the key's data before you provide the entire payload to JWT generator.
At the JWT validation step, after the JWT successfully passes the standard validation (e.g. jsonwebtocken jwt.verify() in Node) you get the decoded payload with encrypted data in sensitiveInfo key. You now just have to decrypt the data and use it as you planned.
This is it.
You should use jwt only to store a token which your API will consume. The token will be generated after a successful login and it can be attached to any request sent to your API and all request should be proceeded only if the token is valid.

Does JWT share/store the secret for signing on both the client and server?

I am working through some architecture issues in my head related to JWT authentication security and I'm trying to figure out the following:
How does JWT securely pass a secret between server and client?
Take a look at the below excerpt from from https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/ ....................
CSRF can be prevented by using synchronized token patterns. This sounds complicated, but all modern web frameworks have support for this.
For example, AngularJS has a solution to validate that the cookie is accessible by only your domain. Straight from AngularJS docs:
'When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain can read the cookie, your server can be assured that the XHR came from JavaScript running on your domain.
You can make this CSRF protection stateless by including a xsrfToken JWT claim:'
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
How does the client create and send a valid request including the xsrfToken claim unless it can first sign the JWT after including the claim? (This xsrfToken after all is what's supposed to keep EvilBob from forging a request right?)
More details regarding my current understanding of the JWT XSRF process can be found here http://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection/.
I can explain how Stormpath does it, there are some other ways as well. Stormpath includes a 'kid' (key id) field in the JWT header, which is the identifier for the API Key ID / Secret pair. The JWT was signed with the Secret, and the ID is stored in key id field. When Stormpath validates the token, it can retrieve the secret. This works across servers and services but is never passed to the client. Using the client to glue separate services together with the secret is extremely insecure.
The client SHOULD NOT generate the JWT, this needs to be done on the server. The server knows the XSRF token and can sign it in the JWT and put it in the cookie.
Hope this information helps!
The article appears to call this the "synchronized token pattern", however the solution described better fits with the Double Submit Cookies method rather than the Synchronizer Token Pattern.
Double submit cookies involves sending the cookie value in a header or body as well as sending it with the browser cookies that are automatically sent. If you are not supporting CORS, then setting a token in a header is secure anyway, as is with any custom header value (e.g. X-Requested-With). This is because a custom header cannot be sent cross-domain in the first place, so verifying that it has transported from the client verifies that it is not from another domain already. As a defence in depth strategy, you can set it to a random value, as explained by this answer.
The random value doesn't need to come from the server, nor be signed. It just needs to be generated by a CSPRNG. If generated client-side, window.crypto should be used for this. All the server does is check that the header and cookie values match.
A third party domain cannot forge a request because even though the cookie value will be sent by the browser automatically from the victim's machine, the attacker cannot include the value in the header or the request body.
With the Synchronizer Token Pattern the CSRF token is generated server-side and stored against the session. This value has to be sent from each form submission and is verified server-side that it matches the stored token.

Chrome Identity API - POST request

I am trying to develop a chrome extension in which I need to use 3rd party Oauth2 authentication. The third party service I want to use, only supports POST requests. But it seems that the launchWebAuthFlow method in the Chrome Identity API, only supports sending GET requests, as all the query parameters are sent in the URL itself. Is this correct? If yes, how should I do authentication?
UPDATE : The API I want to connect is that of Pocket
Partially you're right about POST requirements. But it is only used to initialize Oauth flow.
According to the documentation:
1) You must make a POST request to obtain a request token from Pocket auth service
2) Redirect user to the auth page: https://getpocket.com/auth/authorize?request_token=YOUR_REQUEST_TOKEN&redirect_uri=YOUR_REDIRECT_URI
Which means that you have to make a simple XHR to retrieve request token and then you can use chrome.identity.launchWebAuthFlow function to begin Oauth flow.
Did you try launchWebAuthFlow? You may find that it works. Once authenticated, you can exercise the API via POST, using XMLHttpRequest. (launchWebAuthFlow only handles the authentication, not the API itself.)