@@ -41,6 +41,7 @@ describe('AuthenticationProviders', function () {
4141 'weibo' ,
4242 'phantauth' ,
4343 'microsoft' ,
44+ 'keycloak' ,
4445 ] . map ( function ( providerName ) {
4546 it ( 'Should validate structure of ' + providerName , done => {
4647 const provider = require ( '../lib/Adapters/Auth/' + providerName ) ;
@@ -65,7 +66,7 @@ describe('AuthenticationProviders', function () {
6566 } ) ;
6667
6768 it ( `should provide the right responses for adapter ${ providerName } ` , async ( ) => {
68- const noResponse = [ 'twitter' , 'apple' , 'gcenter' , ' google'] ;
69+ const noResponse = [ 'twitter' , 'apple' , 'gcenter' , " google" , 'keycloak '] ;
6970 if ( noResponse . includes ( providerName ) ) {
7071 return ;
7172 }
@@ -703,6 +704,255 @@ describe('google play games service auth', () => {
703704 } ) ;
704705} ) ;
705706
707+ describe ( 'keycloak auth adapter' , ( ) => {
708+ const keycloak = require ( '../lib/Adapters/Auth/keycloak' ) ;
709+ const httpsRequest = require ( '../lib/Adapters/Auth/httpsRequest' ) ;
710+
711+ it ( 'validateAuthData should fail without access token' , async ( ) => {
712+ const authData = {
713+ id : 'fakeid' ,
714+ } ;
715+ try {
716+ await keycloak . validateAuthData ( authData ) ;
717+ fail ( ) ;
718+ } catch ( e ) {
719+ expect ( e . message ) . toBe ( 'Missing access token and/or User id' ) ;
720+ }
721+ } ) ;
722+
723+ it ( 'validateAuthData should fail without user id' , async ( ) => {
724+ const authData = {
725+ access_token : 'sometoken' ,
726+ } ;
727+ try {
728+ await keycloak . validateAuthData ( authData ) ;
729+ fail ( ) ;
730+ } catch ( e ) {
731+ expect ( e . message ) . toBe ( 'Missing access token and/or User id' ) ;
732+ }
733+ } ) ;
734+
735+ it ( 'validateAuthData should fail without config' , async ( ) => {
736+ const options = {
737+ keycloak : {
738+ config : null ,
739+ } ,
740+ } ;
741+ const authData = {
742+ id : 'fakeid' ,
743+ access_token : 'sometoken' ,
744+ } ;
745+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
746+ 'keycloak' ,
747+ options
748+ ) ;
749+ try {
750+ await adapter . validateAuthData ( authData , providerOptions ) ;
751+ fail ( ) ;
752+ } catch ( e ) {
753+ expect ( e . message ) . toBe ( 'Missing keycloak configuration' ) ;
754+ }
755+ } ) ;
756+
757+ it ( 'validateAuthData should fail connect error' , async ( ) => {
758+ spyOn ( httpsRequest , 'get' ) . and . callFake ( ( ) => {
759+ return Promise . reject ( {
760+ text : JSON . stringify ( { error : 'hosting_error' } ) ,
761+ } ) ;
762+ } ) ;
763+ const options = {
764+ keycloak : {
765+ config : {
766+ 'auth-server-url' : 'http://example.com' ,
767+ realm : 'new' ,
768+ } ,
769+ } ,
770+ } ;
771+ const authData = {
772+ id : 'fakeid' ,
773+ access_token : 'sometoken' ,
774+ } ;
775+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
776+ 'keycloak' ,
777+ options
778+ ) ;
779+ try {
780+ await adapter . validateAuthData ( authData , providerOptions ) ;
781+ fail ( ) ;
782+ } catch ( e ) {
783+ expect ( e . message ) . toBe ( 'Could not connect to the authentication server' ) ;
784+ }
785+ } ) ;
786+
787+ it ( 'validateAuthData should fail with error description' , async ( ) => {
788+ spyOn ( httpsRequest , 'get' ) . and . callFake ( ( ) => {
789+ return Promise . reject ( {
790+ text : JSON . stringify ( { error_description : 'custom error message' } ) ,
791+ } ) ;
792+ } ) ;
793+ const options = {
794+ keycloak : {
795+ config : {
796+ 'auth-server-url' : 'http://example.com' ,
797+ realm : 'new' ,
798+ } ,
799+ } ,
800+ } ;
801+ const authData = {
802+ id : 'fakeid' ,
803+ access_token : 'sometoken' ,
804+ } ;
805+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
806+ 'keycloak' ,
807+ options
808+ ) ;
809+ try {
810+ await adapter . validateAuthData ( authData , providerOptions ) ;
811+ fail ( ) ;
812+ } catch ( e ) {
813+ expect ( e . message ) . toBe ( 'custom error message' ) ;
814+ }
815+ } ) ;
816+
817+ it ( 'validateAuthData should fail with invalid auth' , async ( ) => {
818+ spyOn ( httpsRequest , 'get' ) . and . callFake ( ( ) => {
819+ return Promise . resolve ( { } ) ;
820+ } ) ;
821+ const options = {
822+ keycloak : {
823+ config : {
824+ 'auth-server-url' : 'http://example.com' ,
825+ realm : 'new' ,
826+ } ,
827+ } ,
828+ } ;
829+ const authData = {
830+ id : 'fakeid' ,
831+ access_token : 'sometoken' ,
832+ } ;
833+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
834+ 'keycloak' ,
835+ options
836+ ) ;
837+ try {
838+ await adapter . validateAuthData ( authData , providerOptions ) ;
839+ fail ( ) ;
840+ } catch ( e ) {
841+ expect ( e . message ) . toBe ( 'Invalid authentication' ) ;
842+ }
843+ } ) ;
844+
845+ it ( 'validateAuthData should fail with invalid groups' , async ( ) => {
846+ spyOn ( httpsRequest , 'get' ) . and . callFake ( ( ) => {
847+ return Promise . resolve ( {
848+ data : {
849+ sub : 'fakeid' ,
850+ roles : [ 'role1' ] ,
851+ groups : [ 'unknown' ] ,
852+ } ,
853+ } ) ;
854+ } ) ;
855+ const options = {
856+ keycloak : {
857+ config : {
858+ 'auth-server-url' : 'http://example.com' ,
859+ realm : 'new' ,
860+ } ,
861+ } ,
862+ } ;
863+ const authData = {
864+ id : 'fakeid' ,
865+ access_token : 'sometoken' ,
866+ roles : [ 'role1' ] ,
867+ groups : [ 'group1' ] ,
868+ } ;
869+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
870+ 'keycloak' ,
871+ options
872+ ) ;
873+ try {
874+ await adapter . validateAuthData ( authData , providerOptions ) ;
875+ fail ( ) ;
876+ } catch ( e ) {
877+ expect ( e . message ) . toBe ( 'Invalid authentication' ) ;
878+ }
879+ } ) ;
880+
881+ it ( 'validateAuthData should fail with invalid roles' , async ( ) => {
882+ spyOn ( httpsRequest , 'get' ) . and . callFake ( ( ) => {
883+ return Promise . resolve ( {
884+ data : {
885+ sub : 'fakeid' ,
886+ roles : 'unknown' ,
887+ groups : [ 'group1' ] ,
888+ } ,
889+ } ) ;
890+ } ) ;
891+ const options = {
892+ keycloak : {
893+ config : {
894+ 'auth-server-url' : 'http://example.com' ,
895+ realm : 'new' ,
896+ } ,
897+ } ,
898+ } ;
899+ const authData = {
900+ id : 'fakeid' ,
901+ access_token : 'sometoken' ,
902+ roles : [ 'role1' ] ,
903+ groups : [ 'group1' ] ,
904+ } ;
905+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
906+ 'keycloak' ,
907+ options
908+ ) ;
909+ try {
910+ await adapter . validateAuthData ( authData , providerOptions ) ;
911+ fail ( ) ;
912+ } catch ( e ) {
913+ expect ( e . message ) . toBe ( 'Invalid authentication' ) ;
914+ }
915+ } ) ;
916+
917+ it ( 'validateAuthData should handle authentication' , async ( ) => {
918+ spyOn ( httpsRequest , 'get' ) . and . callFake ( ( ) => {
919+ return Promise . resolve ( {
920+ data : {
921+ sub : 'fakeid' ,
922+ roles : [ 'role1' ] ,
923+ groups : [ 'group1' ] ,
924+ } ,
925+ } ) ;
926+ } ) ;
927+ const options = {
928+ keycloak : {
929+ config : {
930+ 'auth-server-url' : 'http://example.com' ,
931+ realm : 'new' ,
932+ } ,
933+ } ,
934+ } ;
935+ const authData = {
936+ id : 'fakeid' ,
937+ access_token : 'sometoken' ,
938+ roles : [ 'role1' ] ,
939+ groups : [ 'group1' ] ,
940+ } ;
941+ const { adapter, providerOptions } = authenticationLoader . loadAuthAdapter (
942+ 'keycloak' ,
943+ options
944+ ) ;
945+ await adapter . validateAuthData ( authData , providerOptions ) ;
946+ expect ( httpsRequest . get ) . toHaveBeenCalledWith ( {
947+ host : 'http://example.com' ,
948+ path : '/realms/new/protocol/openid-connect/userinfo' ,
949+ headers : {
950+ Authorization : 'Bearer sometoken' ,
951+ } ,
952+ } ) ;
953+ } ) ;
954+ } ) ;
955+
706956describe ( 'oauth2 auth adapter' , ( ) => {
707957 const oauth2 = require ( '../lib/Adapters/Auth/oauth2' ) ;
708958 const httpsRequest = require ( '../lib/Adapters/Auth/httpsRequest' ) ;
0 commit comments