I've adapted the documentation here to work with Azure AD B2C. I can login successfully, and the auto linking works as intended. However, my website requires the use of a Azure AD protected API. This means that I need to use the Azure AD access token (that I get from the callback from Microsoft AD) as a Bearer for a subsequent REST API call.
How do I keep hold of the access token? And, if the token expires after ~15 mins, how would I refresh that token?
Thanks
Are you intending to call the protected API on behalf of each "user" or is it the application itself which needs to communicate with the protected API.
The user/member tokens can be retieved on behalf of a user/member with IExternalLoginWithKeyService.GetExternalLoginTokens (although this may not be working correctly for members just yet).
They are stored in the database in dbo.umbracoExternalLoginToken, if you check that table do you have access token and refresh token records?
I have been playing around with this today to ensure it's working for members as well as users, so I have code snippets if it's useful (sorry it's for Auth0 instead of Azure AD but setup should be moderatey similar, possibly a little more verbose, I opted for quick and easy).
public class DemoComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.AddBackOfficeExternalLogins(logins =>
{
logins.AddBackOfficeLogin(
cfg =>
{
cfg.AddAuth0WebAppAuthentication("Umbraco.Auth0",
opt =>
{
opt.CallbackPath = "/umbraco-auth0-signin";
opt.Domain = builder.Config["Auth0:Domain"];
opt.ClientId = builder.Config["Auth0:ClientId"];
opt.ClientSecret = builder.Config["Auth0:ClientSecret"];
opt.Scope = "openid profile email offline_access";
})
.WithAccessToken(opt =>
{
opt.Audience = builder.Config["Auth0:DemoProtectedApi"];
});
});
});
}
}
public class ExposeMyTokensController : Controller
{
private readonly IUserService _userService;
private readonly IExternalLoginWithKeyService _externalLogins;
public ExposeMyTokensController(IUserService userService, IExternalLoginWithKeyService externalLogins)
{
_userService = userService;
_externalLogins = externalLogins;
}
[HttpGet("demo")]
public IActionResult BadIdea()
{
var me = _userService.GetUserById(-1);
var myTokens = _externalLogins.GetExternalLoginTokens(me.Key);
return Ok(myTokens);
}
}
If I link my backoffice user with an external account and hit the demo endpoint above I can see all my tokens rendered
Thanks for your help. I'm trying the equivalent for members, but getting nothing here:
var me = _memberService.GetById(int.Parse(User.Identity.GetUserId()));
var myTokens = _externalLogins.GetExternalLoginTokens(me.Key);
'myTokens' is null.
I'm not sure if this is Members vs Users thing, or it's something specific to Azure AD.
I noticed in the Umbraco external login examples for Azure AD, there is a 'options.SaveTokens = true'. This throws an NotImplemented exception if I set this to true, however. Might be a red herring, but it sounds related.. the Umbraco source makes it looks it's been omitted by design, but I can't think why..
Ah - ignore me. It's working (sort of!) if I removed all the members pre-9.4 then re-registered.
The issue I'm having now is that the 'access token' only gets set on the INITIAL auto-link of the member. Any access token used to login subsequently is not getting saved into the 'umbracoExternalLoginTokens' table. I'm not sure if there is a setting I'd need to change somewhere, or if this a bug. Paul - I don't have a 'refresh token' at all, like you do in your screenshot - not sure if that's something to do with it.
Is there a mechanism for manually refreshing access tokens built into Umbraco's external login providers?
I'm running into the same issue. It seems the data in the umbracoExternalLoginToken table is outdated. If you remove the lines from the table they will be added again after the next login. But somehow they are not updated once they exists.
This also returns the old tokens:
var currentMember = await _memberManager.GetCurrentMemberAsync();
var currentMemberIdentityUser = (MemberIdentityUser)currentMember;
var loginTokens = currentMemberIdentityUser.LoginTokens;
I've been trying to debug this for a few hours, but it's unclear why the tokens are outdated.
I am integrating with azure b2c authentication using the open id connect, by using the github, shared (https://github.com/jbreuer/Umbraco-OpenIdConnect-Example). this is for member authentication I am able to authenticate to my azure b2c and receiving all the token, but one of the scope parameter is missing from my access token. This is was tested in umbraco v11.3, and we I do have v8 implementation for the same b2c to get access token, in dot net framework i am getting the scope parameter, but in core the scope parameter is not listing. Also, this si an external api scope that is configured.
Persist and refresh Access Token after external Microsoft B2C login
Hi,
https://our.umbraco.com/documentation/reference/security/external-login-providers/ https://our.umbraco.com/documentation/reference/security/auto-linking/
I've adapted the documentation here to work with Azure AD B2C. I can login successfully, and the auto linking works as intended. However, my website requires the use of a Azure AD protected API. This means that I need to use the Azure AD access token (that I get from the callback from Microsoft AD) as a Bearer for a subsequent REST API call.
How do I keep hold of the access token? And, if the token expires after ~15 mins, how would I refresh that token? Thanks
Hey Rob,
Couple of questions
The user/member tokens can be retieved on behalf of a user/member with IExternalLoginWithKeyService.GetExternalLoginTokens (although this may not be working correctly for members just yet).
They are stored in the database in dbo.umbracoExternalLoginToken, if you check that table do you have access token and refresh token records?
I have been playing around with this today to ensure it's working for members as well as users, so I have code snippets if it's useful (sorry it's for Auth0 instead of Azure AD but setup should be moderatey similar, possibly a little more verbose, I opted for quick and easy).
If I link my backoffice user with an external account and hit the demo endpoint above I can see all my tokens rendered
Hi Paul.
Thanks for your help. I'm trying the equivalent for members, but getting nothing here:
'myTokens' is null.
I'm not sure if this is Members vs Users thing, or it's something specific to Azure AD.
I noticed in the Umbraco external login examples for Azure AD, there is a 'options.SaveTokens = true'. This throws an NotImplemented exception if I set this to true, however. Might be a red herring, but it sounds related.. the Umbraco source makes it looks it's been omitted by design, but I can't think why..
If you're interested the rc for 9.4 is out and this should hopefully work there if you're up for being a tester.
https://www.nuget.org/packages/Umbraco.Cms/9.4.0-rc
Yep this won't work for members just yet, fixed for 9.4 in https://github.com/umbraco/Umbraco-CMS/pull/12093
Hi Paul,
Thanks for adding that fix! Adding 'saveTokens = true' no longer throws an exception. I think I'm still doing something wrong, however.
is now an empty list rather than null. The 'umbracoExternalLoginToken' table is empty in the db.
Here's my config:
Logging in and autolinking works perfectly still.. It's just the retrieval of the external login token afterwards that's still alluding me. Any ideas?
Thanks
Ah - ignore me. It's working (sort of!) if I removed all the members pre-9.4 then re-registered.
The issue I'm having now is that the 'access token' only gets set on the INITIAL auto-link of the member. Any access token used to login subsequently is not getting saved into the 'umbracoExternalLoginTokens' table. I'm not sure if there is a setting I'd need to change somewhere, or if this a bug. Paul - I don't have a 'refresh token' at all, like you do in your screenshot - not sure if that's something to do with it.
Is there a mechanism for manually refreshing access tokens built into Umbraco's external login providers?
You won't get a refresh token unless the scope
offline_access
is requested.Once you have that you should be able to exchange the refresh token for a new access token.
Hi Rob,
I'm running into the same issue. It seems the data in the umbracoExternalLoginToken table is outdated. If you remove the lines from the table they will be added again after the next login. But somehow they are not updated once they exists.
This also returns the old tokens:
I've been trying to debug this for a few hours, but it's unclear why the tokens are outdated.
Did you ever created a bug for this?
Jeroen
Hi Rob,
I created an issue for this: https://github.com/umbraco/Umbraco-CMS/issues/12749
Jeroen
The issue is fixed in this PR: https://github.com/umbraco/Umbraco-CMS/pull/12856
It will be part of Umbraco 10.2!
Umbraco 10.2 RC is out and the issue is fixed there: https://github.com/umbraco/Umbraco-CMS/issues/12749
I've also released a package which uses the umbracoExternalLoginTokens table now that it's fixed: https://www.jeroenbreuer.nl/blog/released-umbraco-openid-connect-example-package/
Jeroen
Hello All,
I am integrating with azure b2c authentication using the open id connect, by using the github, shared (https://github.com/jbreuer/Umbraco-OpenIdConnect-Example). this is for member authentication I am able to authenticate to my azure b2c and receiving all the token, but one of the scope parameter is missing from my access token. This is was tested in umbraco v11.3, and we I do have v8 implementation for the same b2c to get access token, in dot net framework i am getting the scope parameter, but in core the scope parameter is not listing. Also, this si an external api scope that is configured.
https://xxxxdevb2c.onmicrosoft.com/web-api/api-scope this is the scope value which used in v8 dot net framework, but not able to add this type of url scope in dot net core.. as per below:
options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("offline_access");
Any suggestions, on how to add the url type scope in dot net core openid connect.
Thanks,
How to use with the access token when the login page is an external application?
is working on a reply...