1- using Microsoft . AspNetCore . Components ;
1+ using GoogleApis . Blazor . Extensions ;
2+ using Microsoft . AspNetCore . Components ;
3+ using Microsoft . Extensions . Configuration ;
24using Microsoft . JSInterop ;
35using System ;
46using System . Collections . Generic ;
@@ -19,26 +21,30 @@ public class AuthService
1921 {
2022 [ Inject ] IHttpClientFactory HttpClientFactory { get ; set ; }
2123 [ Inject ] IJSRuntime JSRuntime { get ; set ; }
24+ [ Inject ] IConfiguration Configuration { get ; set ; }
2225
2326 /// <summary>
2427 /// Constructs the class.
2528 /// </summary>
2629 /// <param name="jsRuntime"></param>
2730 /// <param name="httpClientFactory"></param>
28- public AuthService ( IJSRuntime jsRuntime , IHttpClientFactory httpClientFactory )
31+ /// <param name="configuration"></param>
32+ public AuthService ( IJSRuntime jsRuntime , IHttpClientFactory httpClientFactory , IConfiguration configuration )
2933 {
3034 JSRuntime = jsRuntime ;
3135 HttpClientFactory = httpClientFactory ;
36+ Configuration = configuration ;
3237 }
3338
3439 /// <summary>
35- /// oAuth2 Step 1. Opens "Select Google Account" page in a new tab and return the value into redirectUrl.
40+ /// oAuth2 Step 1. Opens "Select Google Account" page in a new tab and return the value into redirectUrl. Default prompt is consent, which asked for user permission each time (none for not opening consent page and select account for account select account page).
3641 /// </summary>
3742 /// <param name="clientId"></param>
3843 /// <param name="scopes"></param>
3944 /// <param name="redirectUrl"></param>
45+ /// <param name="promptType"></param>
4046 /// <returns></returns>
41- public async Task RequestAuthorizationCode ( string clientId , List < Scope > scopes , string redirectUrl )
47+ public async Task RequestAuthorizationCode ( string clientId , List < Scope > scopes , string redirectUrl , PromptType promptType = PromptType . Consent )
4248 {
4349 string encodedRedirectUrl = HttpUtility . UrlEncode ( redirectUrl ) ;
4450 if ( scopes == null || scopes . Count == 0 )
@@ -52,7 +58,7 @@ public async Task RequestAuthorizationCode(string clientId, List<Scope> scopes,
5258 }
5359 string scopeString = string . Join ( "+" , scopeStringList ) ;
5460
55- await JSRuntime . InvokeAsync < object > ( "open" , $ "https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?response_type=code&client_id={ clientId } &scope={ scopeString } &redirect_uri={ encodedRedirectUrl } &flowName=GeneralOAuthFlow&access_type=offline&prompt=consent ", "_blank" ) ;
61+ await JSRuntime . InvokeAsync < object > ( "open" , $ "https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?response_type=code&client_id={ clientId } &scope={ scopeString } &redirect_uri={ encodedRedirectUrl } &flowName=GeneralOAuthFlow&access_type=offline&prompt={ promptType . ToDescriptionString ( ) } ", "_blank" ) ;
5662 }
5763
5864 /// <summary>
@@ -77,6 +83,81 @@ public string AuthorizeCredential(string authorizationCode, string clientId, str
7783 return request . Content . ReadAsStringAsync ( ) . Result ;
7884 }
7985
86+ /// <summary>
87+ /// Refresh and create new access token with given resfresh token.
88+ /// </summary>
89+ /// <param name="refreshToken"></param>
90+ /// <param name="clientId"></param>
91+ /// <param name="clientSecret"></param>
92+ /// <param name="redirectUrl"></param>
93+ /// <returns></returns>
94+ public string RefreshAccessToken ( string refreshToken , string clientId , string clientSecret , string redirectUrl )
95+ {
96+ string encodedRedirectUrl = HttpUtility . UrlEncode ( redirectUrl ) ;
97+
98+ var client = HttpClientFactory . CreateClient ( ) ;
99+ client . DefaultRequestHeaders . Accept . Add ( new MediaTypeWithQualityHeaderValue ( "application/x-www-form-urlencoded" ) ) ;
100+ var content = new StringContent ( $ "refresh_token={ refreshToken } &client_id={ clientId } &client_secret={ clientSecret } &redirect_uri={ encodedRedirectUrl } &scope=&grant_type=refresh_token", Encoding . UTF8 , "application/x-www-form-urlencoded" ) ;
101+
102+ var request = client . PostAsync ( "https://oauth2.googleapis.com/token" , content ) . Result ;
103+
104+ var result = request . Content . ReadAsStringAsync ( ) . Result ;
105+
106+ var jsonResult = JsonDocument . Parse ( result ) ;
107+ string accessToken = jsonResult . RootElement . GetProperty ( "access_token" ) . ToString ( ) ;
108+
109+ return accessToken ;
110+ }
111+
112+ /// <summary>
113+ /// Get client id. Only works when client id stored in appsettings.json. You can choose the root value that google credentials stored.
114+ /// </summary>
115+ /// <param name="rootValue"></param>
116+ /// <returns></returns>
117+ public string GetClientId ( string rootValue = "GoogleClient" )
118+ {
119+ return Configuration . GetSection ( rootValue ) . GetSection ( "client_id" ) . Value ;
120+ }
121+
122+ /// <summary>
123+ /// Get client secret. Only works when client id stored in appsettings.json. You can choose the root value that google credentials stored.
124+ /// </summary>
125+ /// <param name="rootValue"></param>
126+ /// <returns></returns>
127+ public string GetClientSecret ( string rootValue = "GoogleClient" )
128+ {
129+ return Configuration . GetSection ( rootValue ) . GetSection ( "client_secret" ) . Value ;
130+ }
131+
132+ /// <summary>
133+ /// Get project id. Only works when client id stored in appsettings.json. You can choose the root value that google credentials stored.
134+ /// </summary>
135+ /// <param name="rootValue"></param>
136+ /// <returns></returns>
137+ public string GetProjectId ( string rootValue = "GoogleClient" )
138+ {
139+ return Configuration . GetSection ( rootValue ) . GetSection ( "project_id" ) . Value ;
140+ }
141+
142+ /// <summary>
143+ /// Gets access token expired or not with given content result. Most of the methods' result can be the contentResult parameter directly.
144+ /// </summary>
145+ /// <param name="contentResult"></param>
146+ /// <returns></returns>
147+ public bool IsAccessTokenExpired ( string contentResult )
148+ {
149+ var jsonResult = JsonDocument . Parse ( contentResult ) ;
150+ string errorMessage = jsonResult . RootElement . GetPropertyExtension ( "error" ) ? . GetProperty ( "errors" ) [ 0 ] . GetProperty ( "message" ) . ToString ( ) ;
151+ string errorReason = jsonResult . RootElement . GetPropertyExtension ( "error" ) ? . GetProperty ( "errors" ) [ 0 ] . GetProperty ( "reason" ) . ToString ( ) ;
152+
153+ if ( errorMessage == "Invalid Credentials" || errorReason == "authError" )
154+ {
155+ return true ;
156+ }
157+
158+ return false ;
159+ }
160+
80161 /// <summary>
81162 /// Get authenticated user's e-mail adress.
82163 /// </summary>
0 commit comments