@@ -1756,3 +1756,387 @@ describe('microsoft graph auth adapter', () => {
1756
1756
} ) ;
1757
1757
} ) ;
1758
1758
} ) ;
1759
+
1760
+ describe ( 'facebook limited auth adapter' , ( ) => {
1761
+ const facebook = require ( '../lib/Adapters/Auth/facebook' ) ;
1762
+ const jwt = require ( 'jsonwebtoken' ) ;
1763
+ const util = require ( 'util' ) ;
1764
+
1765
+ // TODO: figure out a way to run this test alongside facebook classic tests
1766
+ xit ( '(using client id as string) should throw error with missing id_token' , async ( ) => {
1767
+ try {
1768
+ await facebook . validateAuthData ( { } , { clientId : 'secret' } ) ;
1769
+ fail ( ) ;
1770
+ } catch ( e ) {
1771
+ expect ( e . message ) . toBe ( 'Facebook auth is not configured.' ) ;
1772
+ }
1773
+ } ) ;
1774
+
1775
+ // TODO: figure out a way to run this test alongside facebook classic tests
1776
+ xit ( '(using client id as array) should throw error with missing id_token' , async ( ) => {
1777
+ try {
1778
+ await facebook . validateAuthData ( { } , { clientId : [ 'secret' ] } ) ;
1779
+ fail ( ) ;
1780
+ } catch ( e ) {
1781
+ expect ( e . message ) . toBe ( 'Facebook auth is not configured.' ) ;
1782
+ }
1783
+ } ) ;
1784
+
1785
+ it ( 'should not decode invalid id_token' , async ( ) => {
1786
+ try {
1787
+ await facebook . validateAuthData (
1788
+ { id : 'the_user_id' , token : 'the_token' } ,
1789
+ { clientId : 'secret' }
1790
+ ) ;
1791
+ fail ( ) ;
1792
+ } catch ( e ) {
1793
+ expect ( e . message ) . toBe ( 'provided token does not decode as JWT' ) ;
1794
+ }
1795
+ } ) ;
1796
+
1797
+ it ( 'should throw error if public key used to encode token is not available' , async ( ) => {
1798
+ const fakeDecodedToken = {
1799
+ header : { kid : '789' , alg : 'RS256' } ,
1800
+ } ;
1801
+ try {
1802
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1803
+
1804
+ await facebook . validateAuthData (
1805
+ { id : 'the_user_id' , token : 'the_token' } ,
1806
+ { clientId : 'secret' }
1807
+ ) ;
1808
+ fail ( ) ;
1809
+ } catch ( e ) {
1810
+ expect ( e . message ) . toBe (
1811
+ `Unable to find matching key for Key ID: ${ fakeDecodedToken . header . kid } `
1812
+ ) ;
1813
+ }
1814
+ } ) ;
1815
+
1816
+ it ( 'should use algorithm from key header to verify id_token' , async ( ) => {
1817
+ const fakeClaim = {
1818
+ iss : 'https://facebook.com' ,
1819
+ aud : 'secret' ,
1820
+ exp : Date . now ( ) ,
1821
+ sub : 'the_user_id' ,
1822
+ } ;
1823
+ const fakeDecodedToken = {
1824
+ header : { kid : '123' , alg : 'RS256' } ,
1825
+ } ;
1826
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1827
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
1828
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
1829
+ return {
1830
+ kid : '123' ,
1831
+ rsaPublicKey : 'the_rsa_public_key' ,
1832
+ } ;
1833
+ } ;
1834
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
1835
+
1836
+ const result = await facebook . validateAuthData (
1837
+ { id : 'the_user_id' , token : 'the_token' } ,
1838
+ { clientId : 'secret' }
1839
+ ) ;
1840
+ expect ( result ) . toEqual ( fakeClaim ) ;
1841
+ expect ( jwt . verify . calls . first ( ) . args [ 2 ] . algorithms ) . toEqual ( fakeDecodedToken . header . alg ) ;
1842
+ } ) ;
1843
+
1844
+ it ( 'should not verify invalid id_token' , async ( ) => {
1845
+ const fakeDecodedToken = {
1846
+ header : { kid : '123' , alg : 'RS256' } ,
1847
+ } ;
1848
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1849
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
1850
+ return {
1851
+ kid : '123' ,
1852
+ rsaPublicKey : 'the_rsa_public_key' ,
1853
+ } ;
1854
+ } ;
1855
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
1856
+
1857
+ try {
1858
+ await facebook . validateAuthData (
1859
+ { id : 'the_user_id' , token : 'the_token' } ,
1860
+ { clientId : 'secret' }
1861
+ ) ;
1862
+ fail ( ) ;
1863
+ } catch ( e ) {
1864
+ expect ( e . message ) . toBe ( 'jwt malformed' ) ;
1865
+ }
1866
+ } ) ;
1867
+
1868
+ it ( '(using client id as array) should not verify invalid id_token' , async ( ) => {
1869
+ try {
1870
+ await facebook . validateAuthData (
1871
+ { id : 'the_user_id' , token : 'the_token' } ,
1872
+ { clientId : [ 'secret' ] }
1873
+ ) ;
1874
+ fail ( ) ;
1875
+ } catch ( e ) {
1876
+ expect ( e . message ) . toBe ( 'provided token does not decode as JWT' ) ;
1877
+ }
1878
+ } ) ;
1879
+
1880
+ it ( '(using client id as string) should verify id_token' , async ( ) => {
1881
+ const fakeClaim = {
1882
+ iss : 'https://facebook.com' ,
1883
+ aud : 'secret' ,
1884
+ exp : Date . now ( ) ,
1885
+ sub : 'the_user_id' ,
1886
+ } ;
1887
+ const fakeDecodedToken = {
1888
+ header : { kid : '123' , alg : 'RS256' } ,
1889
+ } ;
1890
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1891
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
1892
+ return {
1893
+ kid : '123' ,
1894
+ rsaPublicKey : 'the_rsa_public_key' ,
1895
+ } ;
1896
+ } ;
1897
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
1898
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
1899
+
1900
+ const result = await facebook . validateAuthData (
1901
+ { id : 'the_user_id' , token : 'the_token' } ,
1902
+ { clientId : 'secret' }
1903
+ ) ;
1904
+ expect ( result ) . toEqual ( fakeClaim ) ;
1905
+ } ) ;
1906
+
1907
+ it ( '(using client id as array) should verify id_token' , async ( ) => {
1908
+ const fakeClaim = {
1909
+ iss : 'https://facebook.com' ,
1910
+ aud : 'secret' ,
1911
+ exp : Date . now ( ) ,
1912
+ sub : 'the_user_id' ,
1913
+ } ;
1914
+ const fakeDecodedToken = {
1915
+ header : { kid : '123' , alg : 'RS256' } ,
1916
+ } ;
1917
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1918
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
1919
+ return {
1920
+ kid : '123' ,
1921
+ rsaPublicKey : 'the_rsa_public_key' ,
1922
+ } ;
1923
+ } ;
1924
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
1925
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
1926
+
1927
+ const result = await facebook . validateAuthData (
1928
+ { id : 'the_user_id' , token : 'the_token' } ,
1929
+ { clientId : [ 'secret' ] }
1930
+ ) ;
1931
+ expect ( result ) . toEqual ( fakeClaim ) ;
1932
+ } ) ;
1933
+
1934
+ it ( '(using client id as array with multiple items) should verify id_token' , async ( ) => {
1935
+ const fakeClaim = {
1936
+ iss : 'https://facebook.com' ,
1937
+ aud : 'secret' ,
1938
+ exp : Date . now ( ) ,
1939
+ sub : 'the_user_id' ,
1940
+ } ;
1941
+ const fakeDecodedToken = {
1942
+ header : { kid : '123' , alg : 'RS256' } ,
1943
+ } ;
1944
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1945
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
1946
+ return {
1947
+ kid : '123' ,
1948
+ rsaPublicKey : 'the_rsa_public_key' ,
1949
+ } ;
1950
+ } ;
1951
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
1952
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
1953
+
1954
+ const result = await facebook . validateAuthData (
1955
+ { id : 'the_user_id' , token : 'the_token' } ,
1956
+ { clientId : [ 'secret' , 'secret 123' ] }
1957
+ ) ;
1958
+ expect ( result ) . toEqual ( fakeClaim ) ;
1959
+ } ) ;
1960
+
1961
+ it ( '(using client id as string) should throw error with with invalid jwt issuer' , async ( ) => {
1962
+ const fakeClaim = {
1963
+ iss : 'https://not.facebook.com' ,
1964
+ sub : 'the_user_id' ,
1965
+ } ;
1966
+ const fakeDecodedToken = {
1967
+ header : { kid : '123' , alg : 'RS256' } ,
1968
+ } ;
1969
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
1970
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
1971
+ return {
1972
+ kid : '123' ,
1973
+ rsaPublicKey : 'the_rsa_public_key' ,
1974
+ } ;
1975
+ } ;
1976
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
1977
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
1978
+
1979
+ try {
1980
+ await facebook . validateAuthData (
1981
+ { id : 'the_user_id' , token : 'the_token' } ,
1982
+ { clientId : 'secret' }
1983
+ ) ;
1984
+ fail ( ) ;
1985
+ } catch ( e ) {
1986
+ expect ( e . message ) . toBe (
1987
+ 'id token not issued by correct OpenID provider - expected: https://facebook.com | from: https://not.facebook.com'
1988
+ ) ;
1989
+ }
1990
+ } ) ;
1991
+
1992
+ // TODO: figure out a way to generate our own facebook signed tokens, perhaps with a parse facebook account
1993
+ // and a private key
1994
+ xit ( '(using client id as array) should throw error with with invalid jwt issuer' , async ( ) => {
1995
+ const fakeClaim = {
1996
+ iss : 'https://not.facebook.com' ,
1997
+ sub : 'the_user_id' ,
1998
+ } ;
1999
+ const fakeDecodedToken = {
2000
+ header : { kid : '123' , alg : 'RS256' } ,
2001
+ } ;
2002
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
2003
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
2004
+ return {
2005
+ kid : '123' ,
2006
+ rsaPublicKey : 'the_rsa_public_key' ,
2007
+ } ;
2008
+ } ;
2009
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
2010
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
2011
+
2012
+ try {
2013
+ await facebook . validateAuthData (
2014
+ {
2015
+ id : 'INSERT ID HERE' ,
2016
+ token : 'INSERT FACEBOOK TOKEN HERE WITH INVALID JWT ISSUER' ,
2017
+ } ,
2018
+ { clientId : [ 'INSERT CLIENT ID HERE' ] }
2019
+ ) ;
2020
+ fail ( ) ;
2021
+ } catch ( e ) {
2022
+ expect ( e . message ) . toBe (
2023
+ 'id token not issued by correct OpenID provider - expected: https://facebook.com | from: https://not.facebook.com'
2024
+ ) ;
2025
+ }
2026
+ } ) ;
2027
+
2028
+ it ( '(using client id as string) should throw error with with invalid jwt issuer' , async ( ) => {
2029
+ const fakeClaim = {
2030
+ iss : 'https://not.facebook.com' ,
2031
+ sub : 'the_user_id' ,
2032
+ } ;
2033
+ const fakeDecodedToken = {
2034
+ header : { kid : '123' , alg : 'RS256' } ,
2035
+ } ;
2036
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
2037
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
2038
+ return {
2039
+ kid : '123' ,
2040
+ rsaPublicKey : 'the_rsa_public_key' ,
2041
+ } ;
2042
+ } ;
2043
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
2044
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
2045
+
2046
+ try {
2047
+ await facebook . validateAuthData (
2048
+ {
2049
+ id : 'INSERT ID HERE' ,
2050
+ token : 'INSERT FACEBOOK TOKEN HERE WITH INVALID JWT ISSUER' ,
2051
+ } ,
2052
+ { clientId : 'INSERT CLIENT ID HERE' }
2053
+ ) ;
2054
+ fail ( ) ;
2055
+ } catch ( e ) {
2056
+ expect ( e . message ) . toBe (
2057
+ 'id token not issued by correct OpenID provider - expected: https://facebook.com | from: https://not.facebook.com'
2058
+ ) ;
2059
+ }
2060
+ } ) ;
2061
+
2062
+ // TODO: figure out a way to generate our own facebook signed tokens, perhaps with a parse facebook account
2063
+ // and a private key
2064
+ xit ( '(using client id as string) should throw error with invalid jwt clientId' , async ( ) => {
2065
+ try {
2066
+ await facebook . validateAuthData (
2067
+ {
2068
+ id : 'INSERT ID HERE' ,
2069
+ token : 'INSERT FACEBOOK TOKEN HERE' ,
2070
+ } ,
2071
+ { clientId : 'secret' }
2072
+ ) ;
2073
+ fail ( ) ;
2074
+ } catch ( e ) {
2075
+ expect ( e . message ) . toBe ( 'jwt audience invalid. expected: secret' ) ;
2076
+ }
2077
+ } ) ;
2078
+
2079
+ // TODO: figure out a way to generate our own facebook signed tokens, perhaps with a parse facebook account
2080
+ // and a private key
2081
+ xit ( '(using client id as array) should throw error with invalid jwt clientId' , async ( ) => {
2082
+ try {
2083
+ await facebook . validateAuthData (
2084
+ {
2085
+ id : 'INSERT ID HERE' ,
2086
+ token : 'INSERT FACEBOOK TOKEN HERE' ,
2087
+ } ,
2088
+ { clientId : [ 'secret' ] }
2089
+ ) ;
2090
+ fail ( ) ;
2091
+ } catch ( e ) {
2092
+ expect ( e . message ) . toBe ( 'jwt audience invalid. expected: secret' ) ;
2093
+ }
2094
+ } ) ;
2095
+
2096
+ // TODO: figure out a way to generate our own facebook signed tokens, perhaps with a parse facebook account
2097
+ // and a private key
2098
+ xit ( 'should throw error with invalid user id' , async ( ) => {
2099
+ try {
2100
+ await facebook . validateAuthData (
2101
+ {
2102
+ id : 'invalid user' ,
2103
+ token : 'INSERT FACEBOOK TOKEN HERE' ,
2104
+ } ,
2105
+ { clientId : 'INSERT CLIENT ID HERE' }
2106
+ ) ;
2107
+ fail ( ) ;
2108
+ } catch ( e ) {
2109
+ expect ( e . message ) . toBe ( 'auth data is invalid for this user.' ) ;
2110
+ }
2111
+ } ) ;
2112
+
2113
+ it ( 'should throw error with with invalid user id' , async ( ) => {
2114
+ const fakeClaim = {
2115
+ iss : 'https://facebook.com' ,
2116
+ aud : 'invalid_client_id' ,
2117
+ sub : 'a_different_user_id' ,
2118
+ } ;
2119
+ const fakeDecodedToken = {
2120
+ header : { kid : '123' , alg : 'RS256' } ,
2121
+ } ;
2122
+ spyOn ( jwt , 'decode' ) . and . callFake ( ( ) => fakeDecodedToken ) ;
2123
+ const fakeGetSigningKeyAsyncFunction = ( ) => {
2124
+ return {
2125
+ kid : '123' ,
2126
+ rsaPublicKey : 'the_rsa_public_key' ,
2127
+ } ;
2128
+ } ;
2129
+ spyOn ( util , 'promisify' ) . and . callFake ( ( ) => fakeGetSigningKeyAsyncFunction ) ;
2130
+ spyOn ( jwt , 'verify' ) . and . callFake ( ( ) => fakeClaim ) ;
2131
+
2132
+ try {
2133
+ await facebook . validateAuthData (
2134
+ { id : 'the_user_id' , token : 'the_token' } ,
2135
+ { clientId : 'secret' }
2136
+ ) ;
2137
+ fail ( ) ;
2138
+ } catch ( e ) {
2139
+ expect ( e . message ) . toBe ( 'auth data is invalid for this user.' ) ;
2140
+ }
2141
+ } ) ;
2142
+ } ) ;
0 commit comments