I am using IdentityServer 4 with an Angular 10 client that uses OIDC Client JS:
To redirect a user for signin I am calling signinRedirect on the Angular's client:
UserManager.signinRedirect(args)
That redirects to IdentityServer 4 AcccountController's Login action:
[HttpGet]
public async Task<IActionResult> Login(string returnUrl) {
var vm = await BuildLoginViewModelAsync(returnUrl);
if (vm.IsExternalLoginOnly) {
// we only have one option for logging in and it's an external provider
return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl });
}
return View(vm);
}
Question
I have Google and Facebook External Providers configured in Identity Server.
How to use signinRedirect
and inform IdentityServer to use an external provider, like Google, for login?
I would like to bypass the login page in IdentityServer where there are 3 options:
So the Angular Client would inform Identity Server which login method should be used.
Update
After some research it seems there is a way in the spec to specify which provider to user:
UserManager.signinRedirect({ acr_values: 'IdP:Google' }));
Then on the AccountController's BuildLoginViewModelAsync there is the following:
var context = await _interactionService.GetAuthorizationContextAsync(returnUrl);
if (request?.IdP != null && await _schemeProvider.GetSchemeAsync(request.IdP) != null) {
var local = request.IdP == IdentityServer4.IdentityServerConstants.LocalIdentityProvider;
If I am not wrong the IF
condition and following code is to check which Login Provider should be used: Local or one of the External providers configured.
I debugged context
and got the following:
The AcrValues is parsed but the property IdP is not defined.
Shouldn't AcrValues be the way to solve this? What am I missing?
It is possible to send a message to the identity provider using oidc-client by using the args
parameter of signinRedirect
method.
If you take a look at oidc-client-js/src/SigninRequest.js from their github repository, you can see that you can supply the following optional parameters to the aforementioned method:
data
,prompt
,display
,max_age
,ui_locales
,id_token_hint
,login_hint
,acr_values
,resource
,response_mode
,request
,request_uri
,extraQueryParams
,request_type
,client_secret
,extraTokenParams
,skipUserInfo
Later in the code, on line 75 of this file version, they have this:
for(let key in extraQueryParams){
url = UrlUtility.addQueryParam(url, key, extraQueryParams[key])
}
which means they allow devs to use extraQueryParams
to supply custom parameters.
Now assuming your custom message parameter might be called useExternalProvider
, you should be able to call signInRedirect
like this:
UserManager.signinRedirect({
extraQueryParams: {
useExternalProvider: "google"
}});
To access this parameter on your IdentityServer, find the line which calls GetAuthorizationContextAsync
and inspect the protocol message parameters like this:
var context = await interaction.GetAuthorizationContextAsync(returnUrl);
var externalProviderToUse = context.Parameters.Get("useExternalProvider");
It is usually in BuildLoginViewModelAsync(string returnUrl)
method if you used their QuickStart.
From there you can retrieve the external login parameters from database, or from wherever you keep those parameters from, and instead of redirecting users to the login page, redirect them directly to your ExternalLogin(string provider, string returnUrl)
using RedirectToAction
.
EDIT
If you want to use the acr_values
parameter for this and later in IdentityServer authorization context want to use the Idp
property, you can call:
// "idp:" is case sensitive
UserManager.signinRedirect({ acr_values: 'idp:Google' }));