I have a large number of resource calendars that my users need to have different degrees of access to depending on their roles. I am writing an application to manage those Acl rules, but would like to also manage which calendars appear in end users calendar feeds (i.e. I don't want to have them suddenly see all 130 resource calendars and have to filter through them)
I need to use the CalendarList api access, but when I pass users//calendarList instead of users/me/calendarList authorized with Super Admin credentials, the service returns a 404 response.
My goal is to iterate through my list of shared calendar resources and for-each user who is a reader or freeBusyReader, set their calendarListEntry.hidden to true.
So, I discovered the answer. In order to impersonate a user, you must set the "User" to the email address you wish to impersonate when initializing the service account credential:
public static ServiceAccountCredential Credential(string[] Scopes, string impersonateEmail = null)
{
ServiceAccountCredential cred = ServiceAccountCredential.FromServiceAccountData(credential_stream);
var initializer = new ServiceAccountCredential.Initializer(cred.Id)
{
User = string.IsNullOrEmpty(impersonateEmail)?service_acct:impersonateEmail,
Key = cred.Key,
Scopes = Scopes
};
return new ServiceAccountCredential(initializer);
}
Related
I am doing research on Cognito User Pool, Federated Identities and DynamoDB. In order to achieve fine grained access control, I have to use Cognito Identity Id in my DynamoDB table because anything in user pool cannot be referred in IAM Policy. It is worth mentioning that ${cognito-identity.amazonaws.com:sub} refers to identity id and not the “sub” which we see in Cognito user pool.
The question is that how will I map the item in DynamoDB to the user contact?
For example, consider a scenario, if a user of my application has a pending payment and if I have to contact him regarding payment. Or if a user has reported a problem and I have to lookup his data to do a typical customer support.
As you can already get the app user's data from your database with her unique Cognito identity id, all that's left is to get the user's email address. You can do this in a couple of ways. I'll use Android as an example.
You could parse the JWT id token for the email attribute.See this Stack Overflow answer for details:
Parse JWT token payload data to get certain value in android/java
Alternatively, you could do it this way:
CognitoUserPool userPool = new CognitoUserPool(context, userPoolId, clientId, clientSecret);
CognitoUser user = userPool.getUser(userId);
GetDetailsHandler handler = new GetDetailsHandler() {
#Override
public void onSuccess(final CognitoUserDetails list) {
// Successfully retrieved user details
Map mDetails = list.getAttributes().getAttributes();
String email = mDetails.get("email").toString(); // your user email address
// do stuff with the email address
}
};
user.getDetails(handler);
From the AWS docs:
https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-android-sdk.html
I am using Azure AD B2C and trying to login using username and password in my Xamarin app. After signup, I get the following error:
Microsoft.Identity.Client.MsalServiceException: Returned user identifier does not match the sent user identifier at Microsoft.Identity.Client.Internal.Requests.RequestBase.SaveTokenResponseToCache ()
I am using MSAL for login and when we try to log in with Facebook, it works perfectly.
I found another thing, when I try to login with sign up or sign in policy, I can only login with Facebook, but when i try to login only with sign in policy I can only login with username and password not using Facebook.
MSAL has a user cache that requires you to pass in a User in your AcquireTokenSilentAsync calls.
In the case of Azure AD B2C, the user entries in the MSAL cache don't map 1-to-1 to B2C users, rather they are projected across the different policies being used.
So if you have an app that leverages 3 policies for 1 user, MSAL's user cache will have 3 entries in the user cache.
From a code perspective, this means that in order to use MSAL you need to:
Have a GetUserByPolicy helper method that obtains the appropriate user cache entry based on the policy and using that to obtain the user that's passed in to your AcquireTokenAsync and AcquireTokenSilentAsync calls.
Ensure you are always passing an Authority value in your AcquireTokenSilentAsync calls.
The error "Returned user identifier does not match the sent user identifier" is generally caused by either of these two not being done correctly.
From the Azure AD B2C Xamarin Sample:
AcquireTokenAsync call:
AuthenticationResult ar = await App.PCA.AcquireTokenSilentAsync(App.Scopes, GetUserByPolicy(App.PCA.Users, App.PolicySignUpSignIn), App.Authority, false);
AcquireTokenSilentAsync call:
AuthenticationResult ar = await App.PCA.AcquireTokenAsync(App.Scopes, GetUserByPolicy(App.PCA.Users, App.PolicySignUpSignIn), App.UiParent);
GetUserByPolicy helper method:
private IUser GetUserByPolicy(IEnumerable <IUser> users, string policy)
{
foreach (var user in users)
{
string userIdentifier = Base64UrlDecode(user.Identifier.Split('.')[0]);
if (userIdentifier.EndsWith(policy.ToLower())) return user;
}
return null;
}
Ok, I'm late to the party on this, but in case this helps someone else then this is what worked for me when the 'Returned user identifier does not match the sent user identifier' error appeared.
Try adding this before the AquireLoginAsync / AquireLoginSilentAsync, it will clear any old USER objects from the cache.
foreach (var user in ActiveDirectoryB2CAuthenticationClient.Users)
{
ActiveDirectoryB2CAuthenticationClient.Remove(user);
}
I try to create events for the users in my organization with a service account for which it is not needed that there is a reminder. Things like public holidays etc...
I add to the event a reminders object to override the default:
EventReminder[] reminderOverrides = new EventReminder[] {};
Event.Reminders reminders = new Event.Reminders()
.setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders)
Unit test and functional tests show there are no reminders attached when I check from a service account.
However when I login with user credentials, the default reminders are still visible.
What do I need to do differently so that people are not disturbed early in the morning on a public holiday?
When using the service account you should be aware to impersonate the user and not use the admin account. When an event is created by the admin account the default settings are taken from the user calendar settings. But when you impersonate the user you can turn off the notifications.
From the rest API documentation:
It's possible to specify the email address of the user account with the setServiceAccountUser method of the GoogleCredential factory.
I need to navigate to a web site and set a number of claims for that web site to use, but I cannot find any explanation on how to do it. I must be googling the wrong words.
I'm using c# and .Net framework 4.6.1
Edit 1
I was asked to explain my challenge better. I am developing 2 separate websites. Users will always go to website A where they will authenticated using Azure B2C. Once authenticated they will perform a few actions after which they will be navigated to website B. Azure B2C passes user data to website A using Claims, which I would like to forward to website B
What you need to do is to expose a new login action in your website B. This login action can receive an encrypted token which inside contains the claims you are interested in forwarding to the site B. Once that encrypted token is received, the website B can decrypt it and recreate the claims that you are interested in. You can use the built in JwtSecurityToken Handler:
https://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.jwtsecuritytokenhandler(v=vs.114).aspx
For example:
public string CreateSecurityToken(string audience, IEnumerable<Claim> claims)
{
if (claims == null) return null;
var credentials = new SigningCredentials(
new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes("SOMEKEY")),
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
"http://www.w3.org/2001/04/xmlenc#sha256");
var claimsIdentity = new ClaimsIdentity(claims, "Custom Authentication", System.Security.Claims.ClaimTypes.Name, System.Security.Claims.ClaimTypes.Role);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = claimsIdentity,
TokenIssuerName = TokenIssuer,
AppliesToAddress = "http://" + audience,
Lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddMinutes(GetTokenExpirationMinutes(audience))),
SigningCredentials = credentials
};
var jwtHandler = new JwtSecurityTokenHandler();
var token = jwtHandler.CreateToken(tokenDescriptor);
return jwtHandler.WriteToken(token);
}
this will create a token which you can send to a login method on website B
A claim from website A will not be sent to website B.
This could work this way:
A users logs on to site A (using credentials from B2C)
User saves info into B2C (using Graph API)
Redirect to Site B
User logs on to site B (this can occur without prompting the user, same B2C)
Claim are created for site B, but they can contain values set during step 2
graph API:
https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-devquickstarts-graph-dotnet/
If the info is already in the B2C directory, the example is even more simple, create 2 sites:
https://azure.microsoft.com/nl-nl/documentation/articles/active-directory-b2c-devquickstarts-web-dotnet/
Create a custom attribute to store the information:
https://azure.microsoft.com/nl-nl/documentation/articles/active-directory-b2c-reference-custom-attr/
Create a B2C custom attribute:
Create 2(both) B2C Applications
Create a single B2C sign-in policy using the custom attribute and add it to the claims
Use the same policy in both applications, both should see the same claim
I'm attempting to migrate our code for using the (soon to be deprecated) Google Provisioning API to the Admin SDK Directory API, via the .NET client libraries provided by Google.
In the old Provisioning API (via the .NET client library) a call to get the groups for a domain was very simple:
Google.GData.Apps.AppsService apps = new Google.GData.Apps.AppsService(AppDomain, DomainAdminEmail, AdminPassword);
Google.GData.Apps.Groups.GroupsService service = apps.Groups;
AppsExtendedFeed appsFeed = service.RetrieveAllGroups();
Not exactly rocket science, and the only credentials required were the domain, the domain's admin email, and the admin password. As long as you can supply those three parameters, you can get the groups for any domain.
I've been trying for two days to create an equivalent call using the new Admin SDK Directory API (via the new .NET client library), and it's giving me a very hard time. The only way that I've been able to get it to work at all is to create a Service Account for the project associated with the domain's admin email, including generation of a private key file, based on a useful post by mwpreston):
//Create security certificate using private key file and password.
var certificate = new X509Certificate2(pathToPrivateKeyFile, privateKeyPassword, X509KeyStorageFlags.Exportable);
//Create a service credential using the certificate, admin email and API scopes.
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
User = adminUserEmail,
Scopes = scopes
}.FromCertificate(certificate));
//Create Directory Service using the service credential and the application name.
var dirservice = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = applicationName
});
var groupsListRequest = dirservice.Groups.List();
groupsListRequest.Domain = domain;
domainGroups = groupsListRequest.Execute();
However, because the Service Account is associated with a specific domain (as specified in the admin email account for the Service Account) it can only be used to request groups from that specific domain.
We have clients with thousands of different domains. It's impractical to create a new Service Account for every client's domain (as well as a private key file).
I've searched and searched for a way to call the DirectoryService in a way that uses the same parameters (domain, admin email and password) but I can't find anything. The documentation for the Admin API .NET client library is extremely sparse and is of no help.
The Provisioning API will be deprecated on April 20th 2015, so someone else there must have been faced with this issue. Can anyone help?
You should use "impersonate" (via .setServiceAccountUser("user#example.com")) while constructing credential. Look for examples here.
You can create a project on Google Developer Console and generate a refresh/access token instead. Here's the link - https://developers.google.com/accounts/docs/OAuth2WebServer
I haven't used the client library hence can't help you with the code. You can use the 'list' API which will give you all the groups for all domains of a customer (if you provide the customerId) - https://developers.google.com/admin-sdk/directory/v1/reference/groups/list