The System consists of a Keycloak 16.0.0 instance and uses Google as an Identity Provider. I want to fail the authentication based on an attribute that is given inside of the google account information.
The JSON from the google API (GET https://admin.googleapis.com/admin/directory/v1/users/{userKey}) looks like this:
{
"kind": "admin#directory#user",
"id": "00000000",
"etag": "xxxx",
"primaryEmail": "test#test.mail.com",
"name": {
"givenName": "User",
"familyName": "Test",
"fullName": "User Test"
},
..........
..........
..........
..........
"organizations": [
{
"name": "Organization5"
}
]
}
After a user logs in through the SSO Google Login, a user in keycloak should only be created when he is in "Organization5".
I tried using a custom script in the default "First Broker Login" flow before the "Create User If Unique(create unique user config)" execution. But I cannot get the keycloak access token from the identity because the identity is not initalized yet.
Is there any easy out-of-the-box solution that I am missing?
Related
I am failing to add an OpenId account to B2C using Microsoft Graph. What needs to be done to do an add operation?
B2C Setup as TestB2C
In Azure B2C the OpenID Connect (to my companies Azure AD) is setup as an Identity Provider.
For this example, take the blurred out B2C above to be TestB2C.onmicorosoft.com and the target openID is "Corporate AD".
Graph Call To Insert User into B2C
{
"accountEnabled": true,
"displayName": "OmegaMan",
"mailNickname": "OmegaM",
"identities": [
{
"signInType": "userName",
"issuer": "TestB2C.onmicrosoft.com",
"issuerAssignedId": "OmegaMan#Corporate.com"
},
{
"signInType": "emailAddress",
"issuer": "TestB2C.onmicrosoft.com",
"issuerAssignedId": "OmegaMan#Corporate.com"
},
{
"signInType": "federated",
"issuer": "Corporate.com",
"issuerAssignedId": "6ab...34"
}
],
"passwordProfile" : {
"forceChangePasswordNextSignIn": false
}
}
The issuerAssignedId is from the settings placed in the Identity Providers section for the OpenId Connect. When I attempt to insert said user, I get this current error:
...
"error": {
"code": "Request_BadRequest",
"message": "A password must be specified to create a new user.",
...
Which for a federated user does not make sense. Note, that in a different add operation for an "email user", this process works; with different settings. What is missing to then add a federated user?
For a federated user, "accountEnabled" is false.
I was able to circumvent the user "Sign-Up" after user insertion. The issue turned out to be, that to have proper federation occur, the proper values need to be in place.
"identities": [
{
"signInType": "federated",
"issuer": "https://login.microsoftonline.com/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/v2.0",
"issuerAssignedId": "YYYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"
What was happening was that I was using "issuer": "myDomain.com" which was not resolving correctly to do a login; to which the user then had to "SignUp" via the federated IP and ended up with two logins.
By changing issuer from a DNS readable name, to the Microsoft login url with my AD directories' ID (the number provided when switching domain in Azure, XXXX-XXX ... btw) and also a proper issuerAssignedId, found from the originating AD issuer, it worked and the user was added.
We're using the client_credentials flow to get access for our application to tenants environments. The application has the correct scopes, and we get an access token that is working for other endpoints like /users but when doing a request like the following we get error messages.
GET https://graph.microsoft.com/beta/me/findRooms
{
"error": {
"code": "ErrorInvalidUser",
"message": "The requested user '{userId}#{tenantId}' is invalid.",
"innerError": {
"request-id": "b72d26a3-d0ad-42eb-a3d3-35951cb42b3d",
"date": "2020-01-21T10:21:28"
}
}
}
I understand that there's no "me" when we're just an application, but how do we access these types of endpoints in that case? Do I have to have a user to act as, as well? That seems to me like it defeats the purpose of a daemon like this. Cannot find any clear documentation on this matter. On this page in the docs on the use a token section they even refer to a /me endpoint, which is incorrect in that case.
I've tried requesting the /users/{id}/findRooms endpoint with all different kinds of ID's I can find in the access token - none of them work.
Other people with the same issue, that have yet to resolve it.
1. Feedback area in docs
2. Github issue
Best regards,
Christopher
Using the /users/{user-id} is the only pattern that will work with client credentials. In your case, this should work, so maybe it's an issue with the id you are using.
To make sure I'm not giving you bad information, I just tested this with an app-only token from the client credentials flow. Parsing that token over at https://jwt.ms, I see the roles claim like so:
"roles": [
"User.Read.All"
]
If first did a GET /users?$select=displayname,id, and this user was included in the response:
{
"displayName": "Adele Vance",
"id": "3103c7b9-cfe6-4cd3-a696-f88909b9a609"
}
This is the id to use in your findRooms call. I did GET /users/3103c7b9-cfe6-4cd3-a696-f88909b9a609/findrooms and got the following response:
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.emailAddress)",
"value": [
{
"name": "Conf Room Adams",
"address": "Adams#M365x330971.onmicrosoft.com"
},
{
"name": "Conf Room Baker",
"address": "Baker#M365x330971.onmicrosoft.com"
},
{
"name": "Conf Room Crystal",
"address": "Crystal#M365x330971.onmicrosoft.com"
},
{
"name": "Conf Room Hood",
"address": "Hood#M365x330971.onmicrosoft.com"
},
{
"name": "Conf Room Rainier",
"address": "Rainier#M365x330971.onmicrosoft.com"
},
{
"name": "Conf Room Stevens",
"address": "Stevens#M365x330971.onmicrosoft.com"
}
]
}
Trying to use MS Graph API from an OAuth 2.0 HTTP client authenticated against an Azure App Registration to list and create contact folders and contacts for any user, with an O365 license, in the same tenant. The Graph API calls, from Postman, return valid JSON results only when the target user is the Azure Global Administrator user that granted the MS Graph API permission's Admin consent for the entire Azure tenant. Trying to access the contacts or contact folders of any other tenant user results in an Access Denied JSON error response.
According to MS documentation, the Azure App Registration's, MS Graph API, Admin Consented, Application Type permission Contacts.ReadWrite should permit access to all users contact folders and contacts.
However, it only works to get the contact folders and contacts of the Admin user that Admin Consented the permission. The Admin Consented, Application Type permission is behaving like a non-Admin Consented, Delegated Type permission.
Shouldn't an App Registration with Admin Consented, Application Type Contacts permission allow access to all tenant user's contacts run without the need for each end user to consent access?
Is this a bug or expected behavior for accessing contacts?
Why is there no "All" constraint for the Contacts Read Write permission?
For permissions that do not offer an "All" constraint element on the permission name, does the App Registration ignore the Application Type Admin Consent and default to the user who consented to the permission, running as that user instead? Doesn't that go against the point of having Admin Consent and Application Type permissions?
Do we need to have each user delegate Contact Folder and Contacts access to the Admin user?
1) Created an Azure App Registration
2) Granted Microsoft Graph API, Application Type, permissions to that Azure App Registration for:
https://graph.microsoft.com/Group.ReadWrite.All https://graph.microsoft.com/Directory.Read.All https://graph.microsoft.com/Contacts.ReadWrite
3) Granted Microsoft Graph API, Delegated Type, permissions to that Azure App Registration for:
offline_access
4) Configured Postman OAuth 2.0 access token with scope:
offline_access https://graph.microsoft.com/Group.ReadWrite.All https://graph.microsoft.com/Directory.Read.All https://graph.microsoft.com/Contacts.ReadWrite
Data has been [OMITTED] from the example below.
Get the contacts of the Azure Global Administrator user (example: admin_user#fake.com) that granted Admin Consent to the MS Graph API Application Type Permissions:
REQUEST:
https://graph.microsoft.com/v1.0/users/admin_user#fake.com/contacts
RESPONSE:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contacts",
"value": [
{
"#odata.etag": "W/\"[OMITTED]\"",
"id": "[OMITTED]",
"createdDateTime": "2019-10-25T17:11:06Z",
"lastModifiedDateTime": "2019-10-30T13:11:13Z",
"changeKey": "[OMITTED]",
"categories": [],
"parentFolderId": "[OMITTED]",
"birthday": null,
"fileAs": "test, Test",
"displayName": "Test test",
"givenName": "Test",
"initials": null,
"middleName": null,
"nickName": null,
"surname": "test",
"title": null,
"yomiGivenName": null,
"yomiSurname": null,
"yomiCompanyName": null,
"generation": null,
"imAddresses": [],
"jobTitle": null,
"companyName": null,
"department": null,
"officeLocation": null,
"profession": null,
"businessHomePage": null,
"assistantName": null,
"manager": null,
"homePhones": [
"666-666-6666"
],
"mobilePhone": "555-555-5555",
"businessPhones": [
"777-777-7777"
],
"spouseName": null,
"personalNotes": "Test",
"children": [],
"emailAddresses": [],
"homeAddress": {},
"businessAddress": {},
"otherAddress": {}
}
]
}
Try to get the contacts of any other user with an O365 License (example: other_user#fake.com):
REQUEST:
https://graph.microsoft.com/v1.0/users/other_user#fake.com/contacts
RESPONSE:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "[OMITTED]",
"date": "2019-11-04T16:40:58"
}
}
}
Get the contact folders of the Azure Global Administrator user (example: admin_user#fake.com) that granted Admin Consent to the MS Graph API Application Type Permissions:
REQUEST:
https://graph.microsoft.com/v1.0/users/admin_user#fake.com/contactfolders
RESPONSE:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contactFolders",
"value": [
{
"id": "[OMITTED]",
"parentFolderId": "[OMITTED]",
"displayName": "Test Contacts Folder"
}
]
}
Try to get the contact folders of any other user with an O365 License (example: other_user#fake.com):
REQUEST:
https://graph.microsoft.com/v1.0/users/other_user#fake.com/contactfolders
RESPONSE:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "[OMITTED]",
"date": "2019-11-04T16:49:42"
}
}
}
Current perms on App Registration
From the documentation:
There are two scenarios where an app can get contacts in another user's contact folder:
If the app has application permissions, or,
If the app has the appropriate delegated permissions from one user, and another user has shared a contact folder with that user, or, has given delegated access to that user. See details and an example.
In other words, when using Delegated scopes a user may only access their own Contacts or Contacts explicitly shared with them.
If you want to access any user's contacts, you need to use the Contacts.Read or Contacts.ReadWrite Application scope.
In general, Exchange-based resources do not use the .All conventions. They rely on the scope type (Application vs Delegated) to determine if the application can see all user or only the authenticated user's resources.
I'm trying to use the Sample Graph API app to change a user's password but I'm getting:
Error Calling the Graph API Response:
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
}
}
}
Graph API Request:
PATCH /mytenant.onmicrosoft.com/users/some-guid?api-version=1.6 HTTP/1.1
client-request-id: ffd564d3-d716-480f-a66c-07b02b0e32ab
date-time-utc: 2017.08.10 03:04 PM
JSON File
{
"passwordProfile": {
"password": "Somepassword1$",
"forceChangePasswordNextLogin": false
}
}
I've tested updating the user's displayName and that works fine.
{
"displayName": "Joe Consumer"
}
AD Application Permissions
I've configured my app permissions as described here.
Check out this article. Seems like it has the same symptoms.
Solution 1:
If you are receiving this error when you call the API that includes only read permissions, you have to set permissions in Azure Management Portal.
Go to Azure Management Portal and click Active Directory.
Select your custom AD directory.
Click Applications and select your Application.
Click CONFIGURE and scroll down to the section 'Permissions to other applications'.
Provide required Application Permissions and Delegated Permissions for Windows Azure Active Directory.
Finally save the changes.
Solution 2:
If you are receiving this error when you call the API that includes delete or reset password operations, that is because those operations require the Admin role of Company Administrator. As of now, you can only add this role via the Azure AD Powershell module.
Find the service principal using Get-MsolServicePrincipal –AppPrincipalId
Get-MsolServicePrincipal | ft DisplayName, AppPrincipalId -AutoSize
Use Add-MsolRoleMember to add it to Company Administrator role
$clientIdApp = 'your-app-id'
$webApp = Get-MsolServicePrincipal –AppPrincipalId $clientIdApp
Add-MsolRoleMember -RoleName "Company Administrator" -RoleMemberType ServicePrincipal -RoleMemberObjectId $webApp.ObjectId
To connect to your B2C tenant via PowerShell you will need a local admin account. This blog post should help with that, see "The Solution" section.
Try below settings, works for me.
Used the below JSON
{
"accountEnabled": true,
"signInNames": [
{
"type": "emailAddress",
"value": "kart.kala1#test.com"
}
],
"creationType": "LocalAccount",
"displayName": "Joe Consumer",
"mailNickname": "joec",
"passwordProfile": {
"password": "P#$$word!",
"forceChangePasswordNextLogin": false
},
"passwordPolicies": "DisablePasswordExpiration",
"givenName": "Joe",
}
Also make sure you assign the application the user account, administrator role which will allow it to delete users link here
I created a project called: "projectprint-123"
https://console.developers.google.com/apis/credentials/oauthclient?project=projectprint-123
Credentials
Web application
Name : projectprint-123
What to ask can the
1. Authorized JavaScript origins
2. Authorized redirect URIs
Put EMPTY? Because I testing localhost.
OK. I proceed to empty.
What is Oauth consent screen?
I only fill in Email address at this part.
OK. I proceed next.
Then I try
https://www.google.com/cloudprint/getauthcode?
printerid=5e0db751-9498-677d-9cf3-3a7284978279&oauth_client_id=254414591833-7lg4a5nnnh009g9ccf613notg8vceunp.apps.googleusercontent.com
Fail:
{ "success": false, "message": "Unknown, used or expired token.",
"request": {
"time": "0",
"params": {
"oauth_client_id": [
"254414591833-7lg4a5nnnh009g9ccf613notg8vceunp.apps.googleusercontent.com"
],
"printerid": [
"5e0db751-9498-677d-9cf3-3a7284978279"
]
} }, "errorCode": 506 }
I using this APIGEE application to send
https://apigee.com/console/others?req={%22resource%22%3A%22https%3A%2F%2Fwww.google.com%2Fcloudprint%2Fgetauthcode%22%2C%22params%22%3A{%22query%22%3A{}%2C%22template%22%3A{}%2C%22headers%22%3A{%22headers_name_0%22%3A%22Content-Type%22%2C%22headers_value_0%22%3A%22application%2Fx-www-form-urlencoded%22}%2C%22body%22%3A{%22attachmentFormat%22%3A%22mime%22%2C%22attachmentContentDisposition%22%3A%22form-data%22}}%2C%22verb%22%3A%22post%22}
I appreciate if you can help.
Thank you.