88using Google . Apis . Auth . OAuth2 . Flows ;
99using Google . Apis . Auth . OAuth2 . Responses ;
1010
11- namespace Improbable . SpatialOS . Platform . Common {
11+ namespace Improbable . SpatialOS . Platform . Common
12+ {
1213 /// <inheritdoc />
1314 /// <summary>
1415 /// This is the abstract base class for SpatialOS platform credentials. Clients should use a concrete credential provider
1516 /// such as <see cref="PlatformRefreshTokenCredential" /> instead of trying to instantiate this class directly.
1617 /// </summary>
17- public abstract class PlatformCredential : UserCredential {
18+ public abstract class PlatformCredential : UserCredential
19+ {
1820 /// <inheritdoc />
1921 /// <summary>
2022 /// </summary>
@@ -29,17 +31,19 @@ protected PlatformCredential(IAuthorizationCodeFlow flow, string userId, TokenRe
2931 /// <summary>
3032 /// This provides support to automatically acquire access tokens from SpatialOS refresh tokens.
3133 /// </summary>
32- public class PlatformRefreshTokenCredential : PlatformCredential {
34+ public class PlatformRefreshTokenCredential : PlatformCredential
35+ {
3336 private const string DefaultTokenFileEnvVar = "SPATIALOS_REFRESH_TOKEN_FILE" ;
3437 private const string DummyUserId = "dummy_user_id" ;
3538 private const string AuthorizationServerUrl = "https://auth.improbable.io/auth/v1/authcode" ;
3639 private const string TokenServerUrl = "https://auth.improbable.io/auth/v1/token" ;
37- private const string RefreshTokenNotFoundMessage = "Please check if environment variable " + DefaultTokenFileEnvVar + " is set to the correct path or try running `spatial init` to fetch and store a new refresh token locally." ;
40+ private const string RefreshTokenNotFoundMessage = "Please check if environment variable " + DefaultTokenFileEnvVar + " is set to the correct path or try running `spatial init` to fetch and store a new refresh token locally." ;
3841
3942 private static readonly Lazy < PlatformRefreshTokenCredential > AutoDetectedLazy =
4043 new Lazy < PlatformRefreshTokenCredential > ( GetTokenCredentialAutomatically ) ;
4144
42- private static readonly ClientSecrets DefaultSecrets = new ClientSecrets {
45+ private static readonly ClientSecrets DefaultSecrets = new ClientSecrets
46+ {
4347 // This client ID is purposely chosen to be compatible with the default settings of the spatial CLI tool
4448 // so that the SDK can reuse the refresh token retrieved and stored via spatial CLI.
4549 ClientId = "improbable_cli_client_go" ,
@@ -48,7 +52,7 @@ public class PlatformRefreshTokenCredential : PlatformCredential {
4852 "SuperTrouperBeamsAreGonnaBlindMeButIWontFeelBlueLifeIAwaysDoCauseSomewhereInTheCrowdTheresYou"
4953 } ;
5054
51- private static readonly IEnumerable < string > DefaultScopes = new List < string > { "[*]:*" } ;
55+ private static readonly IEnumerable < string > DefaultScopes = new List < string > { "[*]:*" } ;
5256
5357 /// <summary>
5458 /// Initializes a new instance of the <see cref="PlatformRefreshTokenCredential" /> class that uses the supplied
@@ -58,18 +62,23 @@ public class PlatformRefreshTokenCredential : PlatformCredential {
5862 /// <param name="tokenServerUrl">The URL of the OAuth token server. Defaults to Improbable's production OAuth token server.</param>
5963 /// <param name="scopes">The scope to request for the OAuth server. Defaults to "[*]:*".</param>
6064 /// <param name="authServerUrl">The URL of the OAuth auth server. Defaults to Improbable's production OAuth auth server.</param>
65+ /// <param name="clientSecrets">The client secrets for the SpatialOS refresh token.</param>
6166 public PlatformRefreshTokenCredential ( string refreshToken , string authServerUrl = null ,
62- string tokenServerUrl = null , IEnumerable < string > scopes = null )
67+ string tokenServerUrl = null , IEnumerable < string > scopes = null , ClientSecrets clientSecrets = null )
6368 : base (
64- new AuthorizationCodeFlow ( new AuthorizationCodeFlow . Initializer (
65- authServerUrl ?? AuthorizationServerUrl ,
66- tokenServerUrl ?? TokenServerUrl ) {
67- Scopes = scopes ?? DefaultScopes ,
68- ClientSecrets = DefaultSecrets
69- } ) ,
69+ new AuthorizationCodeFlow (
70+ new AuthorizationCodeFlow . Initializer (
71+ authServerUrl ?? AuthorizationServerUrl ,
72+ tokenServerUrl ?? TokenServerUrl
73+ )
74+ {
75+ Scopes = scopes ?? DefaultScopes ,
76+ ClientSecrets = clientSecrets ?? DefaultSecrets
77+ } ) ,
7078 DummyUserId ,
71- new TokenResponse { RefreshToken = refreshToken }
72- ) { }
79+ new TokenResponse { RefreshToken = refreshToken }
80+ )
81+ { }
7382
7483 /// <inheritdoc />
7584 /// <summary>
@@ -104,19 +113,36 @@ private static PlatformRefreshTokenCredential GetTokenCredentialAutomatically()
104113 } ;
105114
106115 var tokenFile = possibleTokenFiles . FirstOrDefault ( File . Exists ) ;
107- if ( tokenFile = = null )
116+ if ( tokenFile ! = null )
108117 {
109- // None of the possible token files exists
110- throw new NoRefreshTokenFoundException ( RefreshTokenNotFoundMessage ) ;
118+ try
119+ {
120+ var refreshToken = File . ReadAllText ( tokenFile ) ;
121+ return new PlatformRefreshTokenCredential ( refreshToken ) ;
122+ }
123+ catch ( IOException )
124+ {
125+ throw new NoRefreshTokenFoundException ( RefreshTokenNotFoundMessage ) ;
126+ }
111127 }
112128
113- try {
114- var refreshToken = File . ReadAllText ( tokenFile ) ;
115- return new PlatformRefreshTokenCredential ( refreshToken ) ;
116- }
117- catch ( IOException ) {
118- throw new NoRefreshTokenFoundException ( RefreshTokenNotFoundMessage ) ;
129+ // None of the possible token files exists. Last fallback is the credentials set in the environment of server workers.
130+ var serverRefreshToken = Environment . GetEnvironmentVariable ( "IMPROBABLE_PLATFORM_REFRESH_TOKEN" ) ;
131+ if ( serverRefreshToken != "" )
132+ {
133+ var clientSecrets = new ClientSecrets
134+ {
135+ ClientId = Environment . GetEnvironmentVariable ( "IMPROBABLE_CLIENT_ID" ) ,
136+ ClientSecret = Environment . GetEnvironmentVariable ( "IMPROBABLE_CLIENT_SECRET" )
137+ } ;
138+ if ( clientSecrets . ClientId != "" && clientSecrets . ClientSecret != "" )
139+ {
140+ var credentials = new PlatformRefreshTokenCredential ( serverRefreshToken , null , null , null , clientSecrets ) ;
141+ }
119142 }
143+
144+ // Fail if no form of credentials could be found.
145+ throw new NoRefreshTokenFoundException ( RefreshTokenNotFoundMessage ) ;
120146 }
121147 }
122148}
0 commit comments