19
19
using System . Net . Http ;
20
20
using System . Threading . Tasks ;
21
21
using FirebaseAdmin . Auth . Jwt ;
22
+ using FirebaseAdmin . Auth . Jwt . Tests ;
23
+ using FirebaseAdmin . Auth . Multitenancy ;
22
24
using FirebaseAdmin . Tests ;
23
25
using FirebaseAdmin . Util ;
24
26
using Google . Apis . Json ;
@@ -1759,12 +1761,12 @@ public void RevokeRefreshTokensInvalidUid(TestConfig config)
1759
1761
async ( ) => await auth . RevokeRefreshTokensAsync ( uid ) ) ;
1760
1762
}
1761
1763
1762
- [ Fact ]
1763
- public void CreateSessionCookieNoIdToken ( )
1764
+ [ Theory ]
1765
+ [ MemberData ( nameof ( TestConfigs ) ) ]
1766
+ public void CreateSessionCookieNoIdToken ( TestConfig config )
1764
1767
{
1765
- var config = TestConfig . ForFirebaseAuth ( ) ;
1766
1768
var handler = new MockMessageHandler ( ) { Response = "{}" } ;
1767
- var auth = ( FirebaseAuth ) config . CreateAuth ( handler ) ;
1769
+ var auth = config . CreateAuthWithIdTokenVerifier ( handler ) ;
1768
1770
var options = new SessionCookieOptions ( )
1769
1771
{
1770
1772
ExpiresIn = TimeSpan . FromHours ( 1 ) ,
@@ -1776,89 +1778,110 @@ public void CreateSessionCookieNoIdToken()
1776
1778
async ( ) => await auth . CreateSessionCookieAsync ( string . Empty , options ) ) ;
1777
1779
}
1778
1780
1779
- [ Fact ]
1780
- public void CreateSessionCookieNoOptions ( )
1781
+ [ Theory ]
1782
+ [ MemberData ( nameof ( TestConfigs ) ) ]
1783
+ public void CreateSessionCookieNoOptions ( TestConfig config )
1781
1784
{
1782
- var config = TestConfig . ForFirebaseAuth ( ) ;
1783
1785
var handler = new MockMessageHandler ( ) { Response = "{}" } ;
1784
- var auth = ( FirebaseAuth ) config . CreateAuth ( handler ) ;
1786
+ var auth = config . CreateAuth ( handler ) ;
1785
1787
1786
1788
Assert . ThrowsAsync < ArgumentNullException > (
1787
1789
async ( ) => await auth . CreateSessionCookieAsync ( "idToken" , null ) ) ;
1788
1790
}
1789
1791
1790
- [ Fact ]
1791
- public void CreateSessionCookieNoExpiresIn ( )
1792
+ [ Theory ]
1793
+ [ MemberData ( nameof ( TestConfigs ) ) ]
1794
+ public void CreateSessionCookieNoExpiresIn ( TestConfig config )
1792
1795
{
1793
- var config = TestConfig . ForFirebaseAuth ( ) ;
1794
1796
var handler = new MockMessageHandler ( ) { Response = "{}" } ;
1795
- var auth = ( FirebaseAuth ) config . CreateAuth ( handler ) ;
1797
+ var auth = config . CreateAuth ( handler ) ;
1796
1798
1797
1799
Assert . ThrowsAsync < ArgumentException > (
1798
1800
async ( ) => await auth . CreateSessionCookieAsync (
1799
1801
"idToken" , new SessionCookieOptions ( ) ) ) ;
1800
1802
}
1801
1803
1802
- [ Fact ]
1803
- public void CreateSessionCookieExpiresInTooLow ( )
1804
+ [ Theory ]
1805
+ [ MemberData ( nameof ( TestConfigs ) ) ]
1806
+ public async Task CreateSessionCookieExpiresInTooLow ( TestConfig config )
1804
1807
{
1805
- var config = TestConfig . ForFirebaseAuth ( ) ;
1806
1808
var handler = new MockMessageHandler ( ) { Response = "{}" } ;
1807
- var auth = ( FirebaseAuth ) config . CreateAuth ( handler ) ;
1809
+ var auth = config . CreateAuth ( handler ) ;
1808
1810
var fiveMinutesInSeconds = TimeSpan . FromMinutes ( 5 ) . TotalSeconds ;
1809
1811
var options = new SessionCookieOptions ( )
1810
1812
{
1811
1813
ExpiresIn = TimeSpan . FromSeconds ( fiveMinutesInSeconds - 1 ) ,
1812
1814
} ;
1813
1815
1814
- Assert . ThrowsAsync < ArgumentException > (
1816
+ await Assert . ThrowsAsync < ArgumentException > (
1815
1817
async ( ) => await auth . CreateSessionCookieAsync ( "idToken" , options ) ) ;
1816
1818
}
1817
1819
1818
- [ Fact ]
1819
- public void CreateSessionCookieExpiresInTooHigh ( )
1820
+ [ Theory ]
1821
+ [ MemberData ( nameof ( TestConfigs ) ) ]
1822
+ public async Task CreateSessionCookieExpiresInTooHigh ( TestConfig config )
1820
1823
{
1821
- var config = TestConfig . ForFirebaseAuth ( ) ;
1822
1824
var handler = new MockMessageHandler ( ) { Response = "{}" } ;
1823
- var auth = ( FirebaseAuth ) config . CreateAuth ( handler ) ;
1825
+ var auth = config . CreateAuth ( handler ) ;
1824
1826
var fourteenDaysInSeconds = TimeSpan . FromDays ( 14 ) . TotalSeconds ;
1825
1827
var options = new SessionCookieOptions ( )
1826
1828
{
1827
1829
ExpiresIn = TimeSpan . FromSeconds ( fourteenDaysInSeconds + 1 ) ,
1828
1830
} ;
1829
1831
1830
- Assert . ThrowsAsync < ArgumentException > (
1832
+ await Assert . ThrowsAsync < ArgumentException > (
1831
1833
async ( ) => await auth . CreateSessionCookieAsync ( "idToken" , options ) ) ;
1832
1834
}
1833
1835
1834
- [ Fact ]
1835
- public async Task CreateSessionCookie ( )
1836
+ [ Theory ]
1837
+ [ MemberData ( nameof ( TestConfigs ) ) ]
1838
+ public async Task CreateSessionCookie ( TestConfig config )
1836
1839
{
1837
- var config = TestConfig . ForFirebaseAuth ( ) ;
1838
1840
var handler = new MockMessageHandler ( )
1839
1841
{
1840
1842
Response = @"{
1841
1843
""sessionCookie"": ""cookie""
1842
1844
}" ,
1843
1845
} ;
1844
- var auth = ( FirebaseAuth ) config . CreateAuth ( handler ) ;
1846
+ var auth = config . CreateAuthWithIdTokenVerifier ( handler ) ;
1847
+ var idToken = await CreateIdTokenAsync ( config . TenantId ) ;
1845
1848
var options = new SessionCookieOptions ( )
1846
1849
{
1847
1850
ExpiresIn = TimeSpan . FromHours ( 1 ) ,
1848
1851
} ;
1849
1852
1850
- var result = await auth . CreateSessionCookieAsync ( " idToken" , options ) ;
1853
+ var result = await auth . CreateSessionCookieAsync ( idToken , options ) ;
1851
1854
1852
1855
Assert . Equal ( "cookie" , result ) ;
1853
1856
Assert . Equal ( 1 , handler . Requests . Count ) ;
1854
1857
var request = NewtonsoftJsonSerializer . Instance . Deserialize < JObject > ( handler . LastRequestBody ) ;
1855
1858
Assert . Equal ( 2 , request . Count ) ;
1856
- Assert . Equal ( " idToken" , request [ "idToken" ] ) ;
1859
+ Assert . Equal ( idToken , request [ "idToken" ] ) ;
1857
1860
Assert . Equal ( 3600 , request [ "validDuration" ] ) ;
1858
1861
1859
1862
config . AssertRequest ( ":createSessionCookie" , Assert . Single ( handler . Requests ) ) ;
1860
1863
}
1861
1864
1865
+ [ Fact ]
1866
+ public async Task CreateSessionCookieTenantIdMismatch ( )
1867
+ {
1868
+ var config = TestConfig . ForTenantAwareFirebaseAuth ( "test-tenant" ) ;
1869
+ var auth = ( TenantAwareFirebaseAuth ) config . CreateAuthWithIdTokenVerifier ( ) ;
1870
+ var idToken = await CreateIdTokenAsync ( "other-tenant" ) ;
1871
+ var options = new SessionCookieOptions ( )
1872
+ {
1873
+ ExpiresIn = TimeSpan . FromHours ( 1 ) ,
1874
+ } ;
1875
+
1876
+ var exception = await Assert . ThrowsAsync < FirebaseAuthException > (
1877
+ ( ) => auth . CreateSessionCookieAsync ( idToken , options ) ) ;
1878
+
1879
+ Assert . Equal ( ErrorCode . InvalidArgument , exception . ErrorCode ) ;
1880
+ Assert . Equal ( AuthErrorCode . TenantIdMismatch , exception . AuthErrorCode ) ;
1881
+ Assert . Null ( exception . InnerException ) ;
1882
+ Assert . Null ( exception . HttpResponse ) ;
1883
+ }
1884
+
1862
1885
[ Theory ]
1863
1886
[ MemberData ( nameof ( TestConfigs ) ) ]
1864
1887
public async Task ServiceUnvailable ( TestConfig config )
@@ -1929,27 +1952,35 @@ private static FirebaseUserManager.Args CreateArgs()
1929
1952
} ;
1930
1953
}
1931
1954
1955
+ private static async Task < string > CreateIdTokenAsync ( string tenantId )
1956
+ {
1957
+ var tokenBuilder = JwtTestUtils . IdTokenBuilder ( tenantId ) ;
1958
+ tokenBuilder . ProjectId = TestConfig . MockProjectId ;
1959
+ return await tokenBuilder . CreateTokenAsync ( ) ;
1960
+ }
1961
+
1932
1962
public class TestConfig
1933
1963
{
1934
1964
internal const string MockProjectId = "project1" ;
1935
1965
1936
1966
internal static readonly IClock Clock = new MockClock ( ) ;
1937
1967
1938
- private readonly string tenantId ;
1939
1968
private readonly AuthBuilder authBuilder ;
1940
1969
1941
1970
private TestConfig ( string tenantId = null )
1942
1971
{
1943
- this . tenantId = tenantId ;
1944
1972
this . authBuilder = new AuthBuilder
1945
1973
{
1946
1974
ProjectId = MockProjectId ,
1947
1975
Clock = Clock ,
1948
1976
RetryOptions = RetryOptions . NoBackOff ,
1977
+ KeySource = JwtTestUtils . DefaultKeySource ,
1949
1978
TenantId = tenantId ,
1950
1979
} ;
1951
1980
}
1952
1981
1982
+ public string TenantId => this . authBuilder . TenantId ;
1983
+
1953
1984
public static TestConfig ForFirebaseAuth ( )
1954
1985
{
1955
1986
return new TestConfig ( ) ;
@@ -1969,10 +2000,21 @@ public AbstractFirebaseAuth CreateAuth(HttpMessageHandler handler = null)
1969
2000
return this . authBuilder . Build ( options ) ;
1970
2001
}
1971
2002
2003
+ public AbstractFirebaseAuth CreateAuthWithIdTokenVerifier (
2004
+ HttpMessageHandler handler = null )
2005
+ {
2006
+ var options = new TestOptions
2007
+ {
2008
+ UserManagerRequestHandler = handler ,
2009
+ IdTokenVerifier = true ,
2010
+ } ;
2011
+ return this . authBuilder . Build ( options ) ;
2012
+ }
2013
+
1972
2014
internal void AssertRequest (
1973
2015
string expectedSuffix , MockMessageHandler . IncomingRequest request )
1974
2016
{
1975
- var tenantInfo = this . tenantId != null ? $ "/tenants/{ this . tenantId } " : string . Empty ;
2017
+ var tenantInfo = this . TenantId != null ? $ "/tenants/{ this . TenantId } " : string . Empty ;
1976
2018
var expectedPath = $ "/v1/projects/{ MockProjectId } { tenantInfo } /{ expectedSuffix } ";
1977
2019
Assert . Equal ( expectedPath , request . Url . PathAndQuery ) ;
1978
2020
}
0 commit comments