Azure AD logout issue in multiple browser tabs - azure-active-directory

I have followed Microsoft website sample to setup a web authentication via Azure AD. I have tested the login via Azure AD, and it was able to logged in and out system. But, I noticed there was an issue when logging out from system. When I duplicate for multiple tabs in browser(chrome, firefox), and logout from one of the duplicated tabs. But other duplicated tabs, still remain logged in status even I refresh them. But when I open a new tab to access again, it required me to login. Below is my code for logout, does anyone know what I have missed out?
protected async Task OnLogout()
{
if (await DialogService.Confirm("Are you sure want to logout?", "Logout Confirmation",
new ConfirmOptions() { OkButtonText = "Yes", CancelButtonText = "No" }) == true)
{
await SignOutManager.SetSignOutState();
Navigation.NavigateTo("authentication/logout");
}
}

Related

MS Teams tab app login is not working on IOS Teams App

I am building a Microsoft Teams tab app (https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/what-are-tabs) using React JS. My application has a login form that logs user in with Teams asking for additional permissions then send the access token back to the backend. My login form is working fine on Web and Desktop app version of the MS Teams. But it is not working on IOS MS Teams app.
This is how I login the user.
import {TeamsFx} from '#microsoft/teamsfx';
// rest of the code hidden
try {
let teamsfx = new TeamsFx();
const credentials = await teamsfs.getCredential();
const accessToken = await credentials.getToken([ 'Group.Read.All', 'User.Read' ]);
} catch (e) {
console.log(e.message)
}
when I login on the IOS Teams app, I am getting this error.
Unable to generate the SSO token: App is neither whitelisted nor app resource matches current domain.
What is the potential cause of the issue and how can I fix it?
You need to set the app uri id as api://{fullDomain}/{appId} for you to be able to get tokens. And because you’re getting extra permissions, you need to make sure you are getting consent.

MSAL React is not signing out from application instead it is also signing out from other tabs which are authenticated sessions

I am trying to logout the user in my react application which uses MSAL and with user account abc#mod123.onmicrosoft.com.
Now, there is a tab already opened with portal.azure.com for the same user. When the user gets logged out from the React application, while we are changing the tenant or accessing some links in portal.azure.com, it is asking to reenter the credentials for the user that is signed in before.
It means the Logout is happening even for other url which is having authenticated session for the same user , which is in other tab and opened.
Thus, the user is signing out from identity server instead of application. can any one help on this...
Here is the code snippet for logout,
const { instance } = useMsal();
const isAuthenticated = useIsAuthenticated();
if (isAuthenticated)
instance.logoutRedirect();
MSAL.js logoutRedirect method in v2 - that clears the cache in browser storage and redirects the window to the Azure Active Directory (Azure AD) sign-out page. After sign-out, Azure AD redirects back to the page that invoked logout by default.
Reference : https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-sign-in?tabs=javascript2#sign-out-with-a-popup-window

IdentityServer4 - Login directly from an external provider

I've implemented the option to login from Azure AD. And the client type I'm using is Hybrid. So now, when a user enters a restricted control on my application, he is being redirected to a login page (on the IdentityServer application site) where he can either enter a username and password or login with an Azure AD account.
What I want to be able to do is skip the login page and redirect the user directly to the MS AD login page. Meaning, the user will click a "Login" link on the website, and that will lead him to the Azure AD login page. Once he successful logged in, he will be redirected back to my application (basically the same flow, just save that extra step of entering IdentityServer login page and clicking the external login button).
Is this possible?
In the client options, try setting EnableLocalLogin to false. From the docs:
EnableLocalLogin
Specifies if this client can use local accounts, or external IdPs only. Defaults to true.
I'm using Asp.Net Core Identity as well, and I set the AccountsController to bypass the local page if EnableLocalLogin is false and there is only one external provider, or if the idP is explicitly set in the request.
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Login(string returnUrl = null)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
if (context?.IdP != null)
{
// if IdP is passed, then bypass showing the login screen
return ExternalLogin(context.IdP, returnUrl);
}
var vm = await BuildLoginViewModelAsync(returnUrl, context);
if (vm.EnableLocalLogin == false && vm.ExternalProviders.Count() == 1)
{
// only one option for logging in
return ExternalLogin(vm.ExternalProviders.First().AuthenticationScheme, returnUrl);
}
return View(vm);
}

Permission grant page will always be shown when using IdentityServer4

I've set up a MVC application and the IdentityServer as desribed in the quickstarts. I also use EFCore to persist the confiuration and grants.
Everything works fine, even the Windows authentication.
When I logout from my MVC app using
public async Task Logout()
{
await HttpContext.Authentication.SignOutAsync("Cookies");
await HttpContext.Authentication.SignOutAsync("oidc");
}
I'm logged out as expected.
But when I login again, enter my credentials and click "Login" the next page asking for the permission grants, again. But why? I already set the permissions on my first login. How can I avoid that?
This can be very annoying if I try to implement a SSO using Windows authentification.
Does this problem means that the grants won't be persisted and read from the database?
Found the same problem here
IdentityServer4 not considering PersistedGrants store (user_consent in particular)
So he already opened an issue https://github.com/IdentityServer/IdentityServer4/issues/928
When creating you're client you can turn off consent with the RequireConsent Flag and you can remember it by adding AllowRememberConsent to true
new Client
{
ClientId = "client",
AllowRememberConsent = true
}
you can see the documentation here

Multiple Login Screens and Namespaces

I have a problem I can't figure out, in my application I have two login screens, one for the admin the other for the regular user. These login screens however point to the same controller in the same Auth namespace aside from that I have separated the rest of my controllers and routes into two namespaces; FrontEnd Namespace and BackEnd namespace.
Now my issue right now is when a regular user uses their credentials to login from the backend they are allowed access, I installed this package kodein/acl to handle roles and permissions and it seems to be working because when a user logs in to the backend now they can't do anything. The problem now is that even though they can't do anything they are still able to redirect to admin dashboard.
What I want here is this; when a regular user tries to login to admin backend they are denied access. I am a bit confused, i dunno how to o about it.
Do I have to create separate auth controllers and methods in both namespaces? Is that even possible? How would i go about it?
I use AngularJS for my frontend so in my route file i have this:
Route::group(['domain' => 'admin.website.loc'], function() {
Route::any('{url?}', function($url) {
return view('backend.index');
})->where(['url' => '[-a-zA-Z0-9/]+']);
});
Route::any('{url?}', function($url) {
return view('frontend.index');
})->where(['url' => '[-a-zA-Z0-9/]+']);
Which catch all urls and return to a single Index page,on the front end since i use JWT for authentication it validates the token on the frontend and if invalid or not available takes the user to the login page.
I thought of something else, maybe a temporary measure maybe permanent, i added the following code to my login function():
$url_parts = parse_url($request->url());
$host_parts = explode('.', $url_parts['host']);
if ($host_parts[0] == "admin")
{
$user = User::find(Auth::user()->id);
if (!$user->is('administrator'))
{
Auth::logout();
return response()->json(['error' => 'You Are Not Authorized!']);
}
}
first i get the request url,
then i get the "host" part of the request url and split it using '.' as the delimiter, this way i can check the subdomain.
Since my admin side uses a sub domain i check to see if the login request was from a url with the 'admin' subdomain, if it was then i check the authenticated user's role to see if they're administrator, if they are not, i log them out immediately and return an error message.
This way i don't have to create a separate function and route for the two login screens.

Resources