Harbor: API token generation when using OIDC authentication

Created on 30 Jan 2020  路  7Comments  路  Source: goharbor/harbor

Hi,

I've been able to use https://github.com/goharbor/harbor/wiki/Harbor-FAQs#api to generate a Bearer token.

However when trying to authenticate using that bearer token get the error:

Failed to verify token, error: oidc: id token issued by a different provider, expected "https://OIDC-Endpoint-URL" got "https://my.harbor.url/"

If authenticating through OIDC, are users meant to generate API tokens from Harbor or from the upstream OIDC server?

This issue is a continuation of https://github.com/goharbor/harbor/issues/8033 which is closed so possibly not being monitored.

Most helpful comment

For someone who might end up on this issue, I have managed to get this working with Keycloak.

Keycloak side

Create a new user (I didn't manage to get it working with a service account), following steps similar to this.
Configure the client (that you most likely have already in place if you are using OICD for Harbor), in particular:

Authentication Flow Overrides:
          Browser Flow: browser
          Direct Grant Flow: direct grant

Onboard the user in Harbor

Go to Harbor URL and login with OICD, here use the username and password for the user you have just created.

From an admin user you might want to add this user as a Limited Guest for some of your Harbor Projects.

Retrieve a token from Keycloak and use it in Harbor.

def main():
    url = "https://[$KEYCLOAK_URL]/auth/realms/[$REALM]/protocol/openid-connect/token"
    data = {'grant_type': 'password', 'client_id': '[$HARBOR_CLIENT_NAME]', 'client_secret': '[REDACTED]',
            'scope': 'openid', 'username': '[$USER_NAME]', 'password': '[$USER_PASSWORD]'}
    response = requests.post(url, data=data)
# Get id_token from Keycloak response
    token = response.json()['id_token']
    harbor_url = "https://[$HARBOR_URL]/api/repositories/[$REPOSITORY_NAME]/tags/[$TAG]/scan"
    headers = {'authorization': f"Bearer {token}", 'Content-Type': 'application/json',
               'Accept': 'application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0'}
    harbor_response = requests.get(harbor_url, headers=headers)
#    if harbor_response.status_code == 403:
#        xsrf = __get_xsrf_token(headers['Set-Cookie'])
#        headers = {'Authorization': f"Bearer {token}", "accept": "application/json", "X-Xsrftoken": xsrf}
#        harbor_response = requests.get(harbor_url, headers=headers)
    print(harbor_response.json())

All 7 comments

@reasonerjt Do we have guide for OIDC

Hello,

I would like to ask, how did you manage to get a proper token?

The FAQ descriptions states that in any case you need to perform an initial request with Basic Auth credentials. For a OIDC user, what credentials did you use to perform the initial request? I tried with CLI token but I am still getting 401 (except that it works from Swagger interface).

@Sudneo For OIDC you need to use id token to access API, basic auth is not supported.
@aMozejko1 You need to id token from the OIDC provider you configured.

For someone who might end up on this issue, I have managed to get this working with Keycloak.

Keycloak side

Create a new user (I didn't manage to get it working with a service account), following steps similar to this.
Configure the client (that you most likely have already in place if you are using OICD for Harbor), in particular:

Authentication Flow Overrides:
          Browser Flow: browser
          Direct Grant Flow: direct grant

Onboard the user in Harbor

Go to Harbor URL and login with OICD, here use the username and password for the user you have just created.

From an admin user you might want to add this user as a Limited Guest for some of your Harbor Projects.

Retrieve a token from Keycloak and use it in Harbor.

def main():
    url = "https://[$KEYCLOAK_URL]/auth/realms/[$REALM]/protocol/openid-connect/token"
    data = {'grant_type': 'password', 'client_id': '[$HARBOR_CLIENT_NAME]', 'client_secret': '[REDACTED]',
            'scope': 'openid', 'username': '[$USER_NAME]', 'password': '[$USER_PASSWORD]'}
    response = requests.post(url, data=data)
# Get id_token from Keycloak response
    token = response.json()['id_token']
    harbor_url = "https://[$HARBOR_URL]/api/repositories/[$REPOSITORY_NAME]/tags/[$TAG]/scan"
    headers = {'authorization': f"Bearer {token}", 'Content-Type': 'application/json',
               'Accept': 'application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0'}
    harbor_response = requests.get(harbor_url, headers=headers)
#    if harbor_response.status_code == 403:
#        xsrf = __get_xsrf_token(headers['Set-Cookie'])
#        headers = {'Authorization': f"Bearer {token}", "accept": "application/json", "X-Xsrftoken": xsrf}
#        harbor_response = requests.get(harbor_url, headers=headers)
    print(harbor_response.json())

Thanks @Sudneo I've added a faq referencing your comment

Is there an harbor api to onboard the users created in the OIDC provider or do we have to use the UI?

does anyone know how to get the oidc token with the oidc provider Auth0 ?
I have a user account on a hosted harbor2 registry (not under my control) and would like to find out if/how I can use the API.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cten picture cten  路  3Comments

a-kinder picture a-kinder  路  3Comments

272909106 picture 272909106  路  4Comments

pingcrosby picture pingcrosby  路  3Comments

steveal picture steveal  路  3Comments