Hello, Had some resources to attempt getting our ...
# gooddata-cloud
m
Hello, Had some resources to attempt getting our OIDC setup again but ran into more issues (previous thread) Is there any possibility of hopping on a call to troubleshoot this as we keep running into a wall on this. This is what they tried and the error message received. I did not include all of code as it includes private information, but can privately DM to a rep if needed. 1) With oauthIssuerLocation set to url RESULT: {"detail":"The requested endpoint does not exist or you do not have permission to access it.","status":404,"title":"Not Found","traceId":"c113dc79e53aa3e1944224b84522707a"} 2) With oauthIssuerLocation set to HTML link RESULT: {"detail":"Unable to parse JSON - Unexpected character ('_' (code 95)): was expecting comma to separate Object entries\n at [Source: REDACTED (
StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION
disabled); line: 9, column: 41].","status":400,"title":"Bad Request","traceId":"bbc67d08a4511acd2cee3ae785b15cdf"} cc: @Marc Dusseault
m
Hi Mark, Thank you for this and for sharing more information via direct message. Before making any changes on your end, could you please confirm that you intend to use your own OIDC? Once we receive your confirmation, we will proceed to disable our MANAGED_OIDC entitlement for your organization, and this will also involve your Account Owner. Regarding the issue, after reviewing, we found that the main error is similar to ones we’ve encountered in previous discussions. Please note that the 'id' you are currently using is set to 'alpha.' We recommend updating both the "id" and the DG_ENDPOINT with your organization's ID. Once you do this, the error related to
oauthIssuerLocation
being set as a URL should be resolved. Remember, oauthIssuerLocation must always be a URL, as outlined in our documentation. At this point, we do not believe scheduling a call is necessary. Please await our confirmation once we have disabled our MANAGED_OIDC on your organization. Thank you.
m
@Marc Dusseault looks like we used the wrong code since it has been awhile since we did this. I'll add it to our Monday task
@Mauricio Cabezas yes, we intend to use our own OIDC once we get this to work properly
m
I ran it with "msxwodmudl". It returned the following:
Copy code
{
  "detail": "Can't proceed, OAuth configuration is protected against alteration in the organization.",
  "status": 409,
  "title": "Conflict",
  "traceId": "b010eea56f42de82602a36856b10e4ba"
}
Request:
Copy code
curl --request PUT \
  --header "Authorization: Bearer $GD_TOKEN" \
  --header 'Content-Type: application/vnd.gooddata.api+json' \
  --data '{
  "data": {
    "id": "msxwodmudl",
    "type": "organization",
    "attributes": {
      "name": "LQDigital",
      "hostname": "lqdigital.cloud.gooddata.com",
      "oauthSubjectIdClaim": "sub",
      "oauthIssuerLocation":"accounts.google.com",
      "oauthClientId": "<excluded>"
    }
  }
}'  $GD_ENDPOINT/api/v1/entities/admin/organizations/msxwodmudl
m
After your confirmation I have disabled our OIDC on your org, can you please try now?
m
New result. We're missing the client secret.
Copy code
{
  "detail": "Client Id and Secret must be defined all together with the issuer location (external OIDC provider).",
  "status": 400,
  "title": "Bad Request",
  "traceId": "7b0bec9f80806613e52738758272fc2e"
}
We'll hopefully find the client secret. When we do, we'll run the request again and will follow up with you again with the results.
Thanks
🙌 1
m
@Mauricio Cabezas we were able to get the code to run and don't have any errors this time. cc: @Marc Dusseault are there any other next steps on our end that we need to do? When I login now, I get the following error:
Copy code
{
  "title": "Unauthorized",
  "status": 401,
  "detail": "401 UNAUTHORIZED \"Authorization failed for given issuer \"accounts.google.com\". URI is not absolute\"",
  "traceId": "224bbb2005a949d4f0056be852637b55"
}
m
Hi Mark, this error seems to suggest that you have the “oauthIssuerLocation” set incorrectly. Could you please try using:
Copy code
"<https://accounts.google.com>"
instead of:
Copy code
"<http://accounts.google.com|accounts.google.com>"
m
@Michael Ullock good news we are one step closer! looks like something we need to do on the Google side now is there something we are missing in the code? This is how our OIDC is setup (with sensitive information removed). What URL should we be redirecting to?
j
Hi Mark, I believe the callback URL (or redirect URI) should looks a bit different. First you will need to set the
oauthIssuerId
parameter via the API and then you need to insert the value into the below callback URL:
Copy code
<https://lqdigital.cloud.gooddata.com/login/oauth2/code/><oauthIssuerId>
Let us know if that helped to resolve the issue.
m
Hi Mark, this is a follow-up, I am just wondering if you have some news or progress on this. Feel free to reach out to us if you need still our help.
m
@Mauricio Cabezas it looks like we got it to work but it appears to be stuck in some sort of loading process. Potentially since now we are using our OIDC the username within GoodData doesn't match up with what is in Google? Assume this based on the error of
Copy code
{
  "status": 404,
  "detail": "404 NOT_FOUND \"User is not registered\"",
  "traceId": "5d0fd22d414b13f69bf8709623149521"
}
cc: @Marc Dusseault
image.png
I was able to successfully login using Google though, it just redirects to the forever loading screen after that
m
Hi Mark, I am glad to hear about the progress. The issue here is that the authentication Id in the user on GoodData side does not match with what Google IDP is expecting, hence the authentication loop issue. To get a user's OIDC ID from Google, you must complete an OAuth 2.0 flow with the
openid
scope, which returns an ID token containing the user's unique identifier in the
sub
claim. This involves setting up credentials in the Google Cloud Console, directing the user to the authorization endpoint, and exchanging the authorization code for tokens via Google’s token endpoint. This
sub
value in the decoded ID token will serve as the user authentication ID in GoodData. I recommend checking online resources on how to do this. In the meantime, please set the correct Id I've sent to you via DM.
m
@Moises Morales Hi Moises. I'm working with Mark LQ on this. cc: @Mark Dilson We are planning to map our domain to GoodData results. Is the correct page to use for setting this up? https://help.gooddata.com/doc/growth/en/expand-your-gooddata-platform/gooddata-integr[…]tion/white-label-your-domain/white-label-an-existing-domain/
m
Hi Marc, I'm not sure I fully follow, but generally speaking, you need to configure CORS when making API calls from a different origin, for example, from your app to GoodData: https://www.gooddata.com/docs/cloud/manage-organization/set-up-cors-for-organization/. If this is not what you are looking for, could you please clarify what you mean by "mapping your domain to GoodData results"?
m
Hi.
We want to be able to see GoodData content from one of our domains. Something like: gooddata.ourdomain.com
So if a user logs in successfully (is authorized) they'll be able to view GoodData content from gooddata.ourdomain.com instead of something like ourdomain.gooddata.com.
m
Thanks for clarifying. If you wish to change your hostname (custom URL), you'll have to follow the steps here: https://www.gooddata.com/docs/cloud/manage-organization/change-domain-name/#i-have-a-cloudgooddatacom-domain-a[…]-for-example-analyticsnewcompanycom. Please be aware that there are two ways to go around this: whether you wish to keep ".cloud.gooddata.com" in the hostname or if you want a completely custom URL, e.g.: analytics.newcompany.com. If you decide for the latter, please feel free to DM me with the requested details.
m
No problem and thanks for the information.
1
@Moises Morales Hi Moises. I'm working on the Google OAuth 2.0 flow that will return the sub value. This is new for me. Here's how I understand it: 1. User visits the GoodData dashboard page. 2. If the are not authenticated they will be redirected to the Google authentication in page. 3. Google prompts for consent 4. Consent given and user is sent to the "Redirect URI" page. 5. "Redirect URI" page is responsible for getting the
sub
id value. Is this correct? If yes, do we need to change the redirect uri so it points to a page we control that can perform the check and return the
sub
id value for the user? This is being created to be used with the custom URL mentioned in my previous comments.
m
Hi Marc, your understanding is correct. Since Google doesn't expose this value by default, it must be captured during the authentication flow, I can see it in the logs since the redirect URI is pointing to your GoodData Cloud domain. If this is too cumbersome, let me propose getting the sub by impersonating the user via the following python script: You first need an API key from a service account with domain-wide delegation enabled.
Copy code
from google.auth.transport.requests import Request
from google.oauth2 import service_account
import requests
import json
# === CONFIGURATION ===
SERVICE_ACCOUNT_FILE = 'FILEPATH' # Replace with the path to the API Key
USER_TO_IMPERSONATE = '<mailto:email@domain.com|email@domain.com>'  # Replace with the target user's email
SCOPES = ['openid', 'email', 'profile']
# ======================
# Set up credentials
credentials = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_FILE,
    scopes=SCOPES,
    subject=USER_TO_IMPERSONATE
)
# Refresh token
request = Request()
credentials.refresh(request)
# Use token to get user info (including "sub")
token = credentials.token
response = requests.get(
    '<https://openidconnect.googleapis.com/v1/userinfo>',
    headers={'Authorization': f'Bearer {token}'}
)
print(json.dumps(response.json(), indent=2))
Please be aware that this only works if you are using Google Workspace.
From the output, “sub” is the AuthID.
m
I have a solution built that can return the
sub
value, but we would need to change the
redirect uri
value to point to it. Currently I think it points to https://lqdigital.cloud.gooddata.com/login/oauth2/code/lqdigital.cloud.gooddata.com. The new
redirect_uri
is: https://insights.lqdigital.com/auth/callback Provided my solution works, my plan is to get the
sub
id on consent and push it into GoodData using this, replacing <user-sub-claim> with the user's
sub
id value:
Copy code
curl --request POST \
  --header "Authorization: Bearer $API_TOKEN" \
  --header 'Content-Type: application/vnd.gooddata.api+json' \
  --data '{
      "data": {
        "id": "john.doe",
        "type": "user",
        "attributes": {
          "authenticationId": "<user-sub-claim>"
        },
        "relationships": {
          "userGroups": {
            "data": [ {
              "id": "adminGroup",
              "type": "userGroup"
            } ]
          }
        }
      }
}' $HOST_URL/api/v1/entities/users
Related question: Is there a way for us to change the
redirect_uri
with the GoodData api?
m
Sounds promising 🙂
The redirect_uri structure is hardcoded and cannot be set via API, but if you are using
"oauthIssuerId"
parameter in your GoodData organization settings, Google will expect the following redirect URI: https://gooddata_domain/login/oauth2/code/oauthIssuerId. If you omit
"oauthIssuerId"
, then the URI will default to https://gooddata_domain/login/oauth2/code/gooddata_domain.
m
I discovered a misunderstanding on my part on how the OAuth works, so my suggested solution likely will not work. I'm looking into it a little more now. I might take you up on the suggestion to use the code you shared early next week. Thanks.
👍 1
m
Please keep us posted.
m
Last question for today: Is the following correct regarding the OIDC ID requirement?: 1. We get the required user OIDC ID values for all users. This is done separate from the Google authentication into GoodData step. 2. We send you the OIDC ID values along with associated user names. 3. You'll update the user records with the OIDC ID values. 4. Users will then be able to authenticate into GoodData through Google.
m
This sounds more like JIT provisioning, this is not supported by Google IDP as it does not support custom scopes. Once you get the sub value, you will need to either create the user with this info or map an existing user to the new sub by updating it.
m
Ok. Thanks again and I hope you have nice weekend.
m
No problem. You too, Marc!
m
@Moises Morales I have the sub id. I was going to use the api call below to update my user. Is this the correct api call to use? If yes: 1. How do I get the "id" value? 2. Is it okay to use the "relationships" data? Source: https://www.gooddata.com/docs/cloud/manage-organization/set-up-authentication/#api-based-provisioning
Copy code
curl --request POST \
  --header "Authorization: Bearer $API_TOKEN" \
  --header 'Content-Type: application/vnd.gooddata.api+json' \
  --data '{
      "data": {
        "id": "john.doe",
        "type": "user",
        "attributes": {
          "authenticationId": "<user-sub-claim>"
        },
        "relationships": {
          "userGroups": {
            "data": [ {
              "id": "adminGroup",
              "type": "userGroup"
            } ]
          }
        }
      }
}' $HOST_URL/api/v1/entities/users
m
Those are good news 🙂 1. The id value is arbitrary and it is only to identify the user in the GoodData. It can be set to anything.
2. Yes, please define the relationship data. It determines the group the new user will belong to (the workspace, datasources and rest of privileges it will have).
m
I was planning to use this to update a user. Since it's for updating, do I need the id for the target user? Also, since it is an update, is it okay to leave out the "relationships"?
m
Since you are updating an existing user, I recommend using the following endpoint instead:
/api/v1/entities/users/id?include=userGroups
Notice that I am using the parameter
?include=userGroups
this will return the user groups the user belongs to and you will have to include them in the call to avoid removing them. This is particularly important in case you are updating an org admin user, if the user is removed from the admin group, you will lose access to the organization and the API token will not have any privileges anymore (you won't be able to undo the changes). With this said, the endpoint only supports PUT (since the user already exists), and the headers to use are content-type: application/vnd.gooddata.api+json and accept: application/vnd.gooddata.api+json. Let me know how it goes.
m
A few follow up question: 1. Do you have a link to the documentation on that api call? 2. I want to make sure I understand you directions correctly. Is the following true? a. Including
?include=userGroups
means that all of the user groups currently assigned to a user will remain assigned to the user. b. If
?include=userGroups
is NOT included, I need to include all of the groups I want assigned to the user. 3. Can you add my id in if I share it with you? I want to see if works.
m
1. https://www.gooddata.com/docs/cloud/api-and-sdk/api/api_reference_all/#operation/updateEntity@Users 2. a. The parameter is included in the endpoint of your GET all to get the user details. Once you get the body with the user groups (relationships) you can edit any details. b. The parameter is not relevant in the PUT call, as it will not have any consequences as to what you include in the body, e.g. if you exclude the relationships, using the parameter, will not add them, they must be present in the body. 3. I am not sure I follow, do you want me to update the user on your behalf? Please note that this is a self service task and we should not interfere with user provisioning, but if you run into any issues, I will be glad to step in.
m
Ok. Thanks. And you were correct for question #3 where I was checking if you could do it on my behalf. --- Some good news and some bad news. • Good news: ◦ I was able to use the api and update the authenticationId for my account with the Google id and can now get into GoodData. • Bad news: ◦ After changing the authenticationId for my account I lost access to the api and can no longer see the workspaces. I'm guessing other privileges have been lost as well. I used the api call you suggested for the PUT operation and only included the following in the data object:
Copy code
"data": {
    "attributes": {
        "authenticationId": "<new id>"
    },
    "id": "<my user id>",
    "type": "user"
}
How do I regain access to the api and see the workspaces and regain any account privileges that might have been lost following the api update I performed?
@Moises Morales Shoot. I see now that I blew it. You were clear in your initial explanation regarding the api push and how it would clear the relationships. I read a portion of your follow up comment and mistook it for meaning that if parameters are left out it would be okay. Sorry about this.
As a possible solution can we revert back to the solution where GoodData provides the OIDC ID. I figure if we do this, Mark LQ or a different admin can log back in and change my account's status to admin and let me see the other workspaces. Then we can switch back to the Google OIDC ID auth and I can login.
m
Hi Marc, it is not necessary to revert the OIDC setup, I am able to fix your user. Could you please confirm the id of the user that got removed from the admin group?
m
Hi Moises. User id of the user that was removed from the admin group: fb65a11e-ff21-4b10-be5d-e1fabedaa346
m
The user is fixed.
m
Thanks
m
Hi Marc, I would like to ask if everything is OK now with the Google IDP implementation. Please don't hesitate to let us know if you need a hand with anything else. We'll be glad to continue assisting you.