How to configure keycloak-(nodejs-)connect to use PKCE? - node.js

I have an express app that I want to secure with keycloak-connect. I have not found any documentation or examples of how to set up an Authorization Code Flow with PKCE in this middleware.
I think I have configured Keycloak (IDP) correctly, because authentication from the app fails due to the middleware not transmitting neither code_challenge nor code_challenge_method parameters, which the auth server rejects:
auth_callback
1
error
invalid_request
error_description
Missing parameter: code_challenge_method
state
b720bdf4-daf8-4aa7-8525-be02404396a6
Middleware configuration:
{
realm: 'SomeRealm',
'auth-server-url': 'https://auth-server.url/auth/',
'ssl-required': 'all',
resource: 'Some-client-ID',
'public-client': true,
'confidential-port': 0,
}
Is keycloak-connect even capable of utilising this flow?

keycloak-connect does not support PKCE as of now.
See the discussion I found at https://keycloak.discourse.group/t/keycloak-connect-node-js-pkce/8285 There someone suggests to switch to another library, which supports PKCE (i.e. node-openid-client)
Regarding the server configuration, I guess you followed https://www.keycloak.org/docs/latest/server_admin/#advanced-settings and section about PKCE, so that should be working as expected.

Related

Specify self signed certificate in pact provider testing

I am currently testing my pact contracts using the below provider options
let opts = {
provider: "api",
providerBaseUrl: "https://my-domain.com",
pactUrls: [
path.resolve(
process.cwd(),
"./pacts/pact-api.json"
),
],
validateSSL: false,
changeOrigin: true,
providerVersion: "1.0.0"
}
return new Verifier(opts).verifyProvider().then(output => {
console.log("Pact Verification Complete!")
console.log(output)
})
When I give the base url as https I get the below error:
Uncaught Error: write EPROTO 140574248376192:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:332:
at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:92:16)
If I change the url to have http: it does a redirect (I get redirect status code 308).
The https url is a self signed url, and the self signed certificate is present in all our servers. I have no issues accessing the url from any browser or curl or via express.js.
But if I provide the url directly in provider options, I get the error. I went through the pact documentation and I was not able to find any additional arguments.
Any help to overcome this issue is highly appreciated.
Thanks.
Update:
The issue was running pact inside a docker container. The requests from the container were being blocked by an internal proxy. Once the proxy was bypassed, it worked.
Under the hood, pact-js uses the "pact-ruby-standalone". You can set the certificate for the pact-ruby-standalone using the environment variables SSL_CERT_FILE as documented here: https://github.com/pact-foundation/pact-ruby-standalone/releases#pact-provider-verifier
UPDATE:
The issue was due to VPN/proxy settings on the host which was intercepting the request and presenting an invalid certificate.
ORIGINAL POST:
Whilst Beth is correct in that we do use that Ruby library under the hood, Pact JS actually spins up a proxy which the Ruby standalone actually interacts with - i.e. Ruby talks to a local JS server running http, and the proxy re-issues the request to the service. So the issue is most likely in the Pact JS framework.
There could be a few things happening here:
There is an issue in the library somewhere
There is a configuration issue somewhere we need to get to the bottom of
There is something special about the TLS certificate
Could you please update the bug report at https://github.com/pact-foundation/pact-js/issues/429 ?
We're going to need logs and other information to get to the bottom of it (see https://github.com/pact-foundation/pact-js/blob/master/.github/issue_template.md for how to help us help you).

How to use Firebase Auth's Google Sign-In option with Cypress.io

I need help using Google Sign-In when testing my Angular 6 app with Cypress. It can't use the sign-in popup, and so I'm trying to follow Cypress' advice to "always use cy.request() to talk to 3rd party servers via their APIs." That's from https://docs.cypress.io/guides/references/best-practices.html#Visiting-external-sites which then points us to this example: https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js - more info on how to do this is seen at minute 23 in a presentation by the Cypress author: https://www.youtube.com/watch?v=5XQOK0v_YRE
I'm taking the video solution and trying to modify it for Firebase Auth according to https://firebase.google.com/docs/auth/web/google-signin#advanced-authenticate-with-firebase-in-nodejs but I'm getting stuck on how to obtain the proper id_token and so far I have this code in my commands.js file:
Cypress.Commands.add('login', () => {
var id_token = ___?____;
cy.request({
method: 'POST',
url: 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=[API_KEY]',
body: {
"requestUri": "http://localhost:3500",
"postBody": `id_token=${id_token}&providerId=google.com`,
"returnSecureToken": true,
"returnIdpCredential": true
}
})
})
I believe I need to use a different API to initiate the login and request user credentials, which will include the id_token, and so I tried https://firebase.google.com/docs/auth/web/google-signin#advanced-authenticate-with-firebase-in-nodejs but am not yet skilled enough to pull in external js files (https://apis.google.com/js/platform.js) into Node (This is probably not possible in js files the way it is in html). Using this package: https://github.com/google/google-auth-library-nodejs may be my next attempt. Is there anyone who can pick it up from here?
Similar question at Is it possible to use Cypress e2e testing with a firebase auth project? - but they are signing in with user and pass.

Node & GraphQL Auth

What is the recommended method of handling user authentication and token creation using Node/Graphql? I see a lot of tutorials out there that use a REST endpoint to authorize the user and generate the token.
While I'm new to the GraphQL scene, I don't see why you wouldn't use GraphQL for this.
For example, why not have a query like this which gets sent to a resolver that checks the user/pass and generates a token? :
mutation {
loginUser (
username: "YOURUSERNAME",
password:"YOURPASSWORD"
)
{
token
}
}
Is there a specific reason that the tutorials I've gone through haven't done it this way? Is there some sort of flaw in this method that I'm not aware of?
The official docs explain the reasoning a bit: https://graphql.org/graphql-js/authentication-and-express-middleware/
Reading between the lines a bit, it seems there isn't any official recommendation to not do this, but existing tools expect headers to be used and classic endpoints so this fits better.
If you start talking about OAUTH you're going to have to implement classic URLs anyways as well to complete that dance.

ServiceStack: How do I use custom OAuthProvider to get access to Azure resources

Created custom provider that implements: OAuthProvider, IAuthWithRequest.
Created AuthenticateAttribute that calls PreAuthenticate() method of the provider.
Configured CorsFeature:
Plugins.Add(new CorsFeature(new[] { "http://localhost:23589", "*" },
allowCredentials: true,
allowedHeaders: "Content-Type, Allow, Authorization"));
Problem: when provider's Authenticate method is called to request a code from
"login.microsoftonline.com" (authService.Redirect(PreAuthUrlFilter(this, codeRequest)); ) the following error is thrown:
XMLHttpRequest cannot load https://login.microsoftonline.com/d331431b-899c-4666-8094-e82e6bfc3964/oaut…orts%2fpbi&scope=user_impersonation&state=f8e986304a47427d8c6a76767f2ef573. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:23589' is therefore not allowed access.
What is the correct way to:
Request an auth code from Microsoft
Get the code back in a query string
Request auth Token using the code
Authorization Code Grant Flow Diagram
Have a look at ServiceStack.Authentication.Aad. At a minimum this should offer a unit-tested reference implementation. Or perhaps you can use the NuGet package directly.
I encourage you to clone the repository where you can step through the stand-alone SelfHostTest as well as unit tests.
To my knowledge, CORS should not be necessary. I may be wrong. But in my implementation the JSON responses coming from Microsoft were handled by the server, not the web browser.
I'm sorry for not including a code sample in this response; it would be difficult to take a single snippet of code from that repository. The entire repository is the answer to your fundamental question.
Full disclosure: I'm the author of that plugin and garner Imaginary Internet Points for its use.

Making Azure Mobile App accept custom authentication with Node backend

I'm trying to implement a custom authentication in an Azure Mobile App (not the old Mobile Service) with a Node.js backend, with actions I can't quite translate into Node. An earlier question states that custom authentication "just works" with a .NET backend. I am having trouble getting
I have copied Joy of code's example JWT generation (gist here). I invoke it like this (inlining the aud and userId):
zumoJWT(expiry,"MyAud","MyAud:1455527189540927",req.azureMobile.configuration.auth.secret);
My registration API returns the following JSON
{"user":{"userid":"MyAud:1455527189540927"},"token":"a lot of base64"}
Which I put into the Android MobileServiceClient with this code
JsonObject userob=ob.get("user").getAsJsonObject();
MobileServiceUser user=new MobileServiceUser(userob.get("userid").getAsString());
user.setAuthenticationToken(ob.get("token").getAsString());
mClient.setCurrentUser(user);
Which gives me the error message
com.microsoft.windowsazure.mobileservices.MobileServiceException: {"name":"JsonWebTokenError","message":"invalid signature"
The next time I invoke an API. How do I make my app accept the login token?
Edit: The server-side logs say
2016-02-15T11:42:35 PID[180] Warning JWT validation failed: IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 1,
Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
)
',
token: '{"alg":"HS256","typ":"JWT","kid":0}.{"exp":null,"iss":"urn:microsoft:windows-azure:zumo","ver":2,"aud":"MyAud","uid":"MyAud:1455534835642715"}
RawData: a lot of base64'..
I figured it out. I needed to have
mobile.configuration.auth.validateTokens=false;
in app.js (or rather, not have the same variable set to true).

Resources