How to Authenticate to the WebDAV API?

Server configuration

Operating system:
Debian 11

Web server:
Nginx 1.18.0

ownCloud version: (see ownCloud admin page)
Infinite Scale 2.0.0-rc.1

Updated from an older ownCloud or fresh install:
Fresh Install, Binary Setup

I am attempting to integrate 3rd party software to allow creation of folders and uploading of files into my Owncloud Infinite Scale server. Pouring over the documentation, I have found endpoints for performing these actions with WebDAV API commands.

My difficulty is in authenticating to this API. It is using OpenID Connect as far as I can tell. I have been unable to locate any documentation on the endpoints to use for authenticating and receiving my access token so I can make the desired API calls.

Iā€™ve been able to get API calls to work by scraping an access token out of a browser session. It appears OpenID Connect typically uses a browser for a user to input their credentials. As this will be a system authenticating and not a person, this is not a flow that will work for my use case.

Is there documentation that someone can point me to on how to authenticate against this API or setup an API client that uses an API key or something?

I appreciate any help that can be offered.

App passwords / tokens for 3rd party WebDAV access are on the roadmap:
App Passwords / Tokens for legacy WebDAV clients Ā· Issue #197 Ā· owncloud/ocis Ā· GitHub

There is oidc-agent which makes oidc more usable from the cli.

See the rclone docs as an example how to use it: WebDAV (rclone.org)

Or for curl: General Usage - oidc-agent (gitbook.io)

I appreciate your responses. Iā€™ve installed the oidc-agent and have been working with that to get authenticated. Iā€™ll have to do some pretty wild work arounds to get all this working, but I think Iā€™ll be able to get there. It sure would be nice if OCIS would provide an API for file operations with more machine usable authentication flow. Iā€™m glad app passwords are on the road map.

Thanks again for pointing me in the right direction.

1 Like

It would be awesome if you could share notes about the process you went to, maybe others can benefit from that as well?

Whatever form you likeā€¦

Thanks,
Klaas

2 Likes

Using an external fully featured IDP like Keycloak might solve the issue (or make it less painful), but I fully agree that the default oCIS internal IDP is pretty hard to use if you want to work with the API. Not only that the feature set quite limited, also the documentation is non-existent and users have to read the codeā€¦ Here is what I have done to obtain an OIDC access token from the command line in a non-interactive way:


## Login with a username/password to get an OIDC session. Im going to use a default demo user "einstein/relativity". Username and password need to be replaced. A successful request returns a JSON.

curl -v -b /tmp/ocis.txt -c /tmp/ocis.txt -X POST "https://ocis.example.org/signin/v1/identifier/_/logon" \
    -H "Origin: https://ocis.example.org" \
    -H 'Kopano-Konnect-XSRF: 1' \
    -H 'Content-Type: application/json' \
    -d '{"params":["einstein","relativity","1"], "hello": {}}'

{
  "success": true,
  "state": "",
  "hello": {
    "state": "",
    "flow": "",
    "success": true,
    "username": "einstein",
    "displayName": "Albert Einstein",
    "branding": {}
  }
}

## Request an access token using the active OIDC session. The access token will be returned as URL parameter of the `location` Header and need to be extracted by some bash magic or copied manually.  CAUTION: The default lifetime of an access tokens is `expires_in=300` (5min) which is quiet short if you have to maintain it manually. 

curl -LIs -b /tmp/ocis.txt -c /tmp/ocis.txt -G "https://ocis.example.org/signin/v1/identifier/_/authorize"  \
    --data-urlencode "scope=openid profile email" \
    --data-urlencode "response_type=token" \
    --data-urlencode "client_id=web" \
    --data-urlencode "redirect_uri=https://ocis.example.org/" \
    | grep "location:"

location: https://ocis.example.org/?access_token=eyJhbGciOiJQUzI1NiIsImtpZCI6InByaXZhdGUta2V5IiwidHlwIjoiSldUIn0.eyJhdWQiOiJ3ZWIiLCJleHAiOjE2NzAwNjk1ODAsImp0aSI6IkdmdGNrZ3BjcWdOMVBoVjZqOGZvYmh1TldXWC1keVdNIiwiaWF0IjoxNjcwMDY5MjgwLCJpc3MiOiJodHRwczovL29jaXMub3duY2xvdWQuY29tIiwic3ViIjoiaDlKSTVFa0NSWm1XU2NhSEB1bTlNa09nZUdTc2VyTnhMNHNIaGIxaXhsaVMtdGt0cWRXbzJNRGo0cTFrdnBick1BMVdwMFA0ZWdMeHhsRk02ckJvRkFBIiwibGcudCI6IjEiLCJzY3AiOiJvcGVuaWQiLCJsZy5pIjp7ImRuIjoiQWxiZXJ0IEVpbnN0ZWluIiwiaWQiOiJ1aWQ9ZWluc3RlaW4sb3U9dXNlcnMsbz1saWJyZWdyYXBoLWlkbSIsInVuIjoiZWluc3RlaW4ifSwibGcucCI6ImlkZW50aWZpZXItbGRhcCJ9.FlDK8_K7qwB-Ydzo7UXpT5ckXuZFo3yExGElBLmTAKhYJajMf7AvWsB7rhnk2WDnIBFILoNSa5X7S0Tsd_ufEoqnS7iJTFNXD_UsfMtojKkfpXvBiVG7sVresMjgyh9Ufy2X2J_Kw8g7GbGL9tJUuE8Mnc1pral9h5VBHcJMXTbDof-WoPdCe8Z741bQkZImSXgfLGCsCky1hhTx5nTmAUY0NqnVRynRpcnqH1mfTO5zgBZhMp-uNSiPAhHA4Y4E3UNe_gELnYkV_rVlZRjm812Cp1W1HjzQTFhm5dyb_kqboN0ORK5FhdW8FblgLq6Kkj92z4EAv0cxXMd16V4_-VGI3YpqSXwFfMlEc9nmaYpAAwgCSeWLt5mWUkxzfKD3jpzjv58rBvH1P_nxo1-icZ8b7H9LlO9Uui6YhHcUP5SXjX_spgMl8LLPP17kRA_vnFHrQzrrm1sZHQcCsCiWhBpr7pHKPT0I6p0OQM-Y0PlGEwHNQDJP0jJ8at8F-JHzom_8_yvChkHJXjXvqdJGak2YmT1UUxSvleClnPEAhnzgwVLwJE58pfjdP5LT1iYtXsZGSkpPVC_eQQW63PDdTNrVYsc7t4xUHYjCw-06BYzBexioSeMoPFKyjUD745cWVZH-PSjmaW2_kxOSJpFgyg-ysQE1mU_kppGO1I5GSZs&expires_in=300&scope=openid&session_state=a774dc3ba824921f0be83d26b82637e0a342ffc4b0199e0274e473bd1c34ff97.f8xsxfkf3tJC0pf_NSL2c6c0u6OJ5aJ76oZaMzXcMnQ&state=&token_type=Bearer

## The token from above can be used to access the API.

token='eyJhbGciOiJQUzI1NiIsImtpZCI6InByaXZhdGUta2V5IiwidHlwIjoiSldUIn0.eyJhdWQiOiJ3ZWIiLCJleHAiOjE2NzAwNjk1ODAsImp0aSI6IkdmdGNrZ3BjcWdOMVBoVjZqOGZvYmh1TldXWC1keVdNIiwiaWF0IjoxNjcwMDY5MjgwLCJpc3MiOiJodHRwczovL29jaXMub3duY2xvdWQuY29tIiwic3ViIjoiaDlKSTVFa0NSWm1XU2NhSEB1bTlNa09nZUdTc2VyTnhMNHNIaGIxaXhsaVMtdGt0cWRXbzJNRGo0cTFrdnBick1BMVdwMFA0ZWdMeHhsRk02ckJvRkFBIiwibGcudCI6IjEiLCJzY3AiOiJvcGVuaWQiLCJsZy5pIjp7ImRuIjoiQWxiZXJ0IEVpbnN0ZWluIiwiaWQiOiJ1aWQ9ZWluc3RlaW4sb3U9dXNlcnMsbz1saWJyZWdyYXBoLWlkbSIsInVuIjoiZWluc3RlaW4ifSwibGcucCI6ImlkZW50aWZpZXItbGRhcCJ9.FlDK8_K7qwB-Ydzo7UXpT5ckXuZFo3yExGElBLmTAKhYJajMf7AvWsB7rhnk2WDnIBFILoNSa5X7S0Tsd_ufEoqnS7iJTFNXD_UsfMtojKkfpXvBiVG7sVresMjgyh9Ufy2X2J_Kw8g7GbGL9tJUuE8Mnc1pral9h5VBHcJMXTbDof-WoPdCe8Z741bQkZImSXgfLGCsCky1hhTx5nTmAUY0NqnVRynRpcnqH1mfTO5zgBZhMp-uNSiPAhHA4Y4E3UNe_gELnYkV_rVlZRjm812Cp1W1HjzQTFhm5dyb_kqboN0ORK5FhdW8FblgLq6Kkj92z4EAv0cxXMd16V4_-VGI3YpqSXwFfMlEc9nmaYpAAwgCSeWLt5mWUkxzfKD3jpzjv58rBvH1P_nxo1-icZ8b7H9LlO9Uui6YhHcUP5SXjX_spgMl8LLPP17kRA_vnFHrQzrrm1sZHQcCsCiWhBpr7pHKPT0I6p0OQM-Y0PlGEwHNQDJP0jJ8at8F-JHzom_8_yvChkHJXjXvqdJGak2YmT1UUxSvleClnPEAhnzgwVLwJE58pfjdP5LT1iYtXsZGSkpPVC_eQQW63PDdTNrVYsc7t4xUHYjCw-06BYzBexioSeMoPFKyjUD745cWVZH-PSjmaW2_kxOSJpFgyg-ysQE1mU_kppGO1I5GSZs'

curl -s -X GET   'https://ocis.example.com/graph/v1.0/me'   -H 'accept: application/json'   -H "Authorization: Bearer $token" | jq
{
  "displayName": "Albert Einstein",
  "id": "4c510ada-c86b-4815-8820-42cdf82c3d51",
  "mail": "einstein@example.org",
  "onPremisesSamAccountName": "einstein"
}

## Discover the personal spaces WebDAV uri

āÆ curl -s -X GET   'https://ocis.example.org/graph/v1.0/me/drives'   -H 'accept: application/json'   -H "Authorization: Bearer $token" | jq
{
  "value": [
    {
      "driveAlias": "personal/einstein",
      "driveType": "personal",
      "id": "166d1210-cdb9-50ab-9f1e-ecb9ef12a304$4c510ada-c86b-4815-8820-42cdf82c3d51",
      "lastModifiedDateTime": "2022-12-03T12:11:43.401852121Z",
      "name": "Albert Einstein",
      "owner": {
        "user": {
          "id": "4c510ada-c86b-4815-8820-42cdf82c3d51"
        }
      },
      "quota": {
        "remaining": 28486905856,
        "state": "normal",
        "total": 0,
        "used": 0
      },
      "root": {
        "eTag": "\"2e7875997c6020906bd0bcd449ce1cf9\"",
        "id": "166d1210-cdb9-50ab-9f1e-ecb9ef12a304$4c510ada-c86b-4815-8820-42cdf82c3d51",
        "webDavUrl": "https://ocis.example.org/dav/spaces/166d1210-cdb9-50ab-9f1e-ecb9ef12a304$4c510ada-c86b-4815-8820-42cdf82c3d51"
      },
      "webUrl": "https://ocis.example.org/f/166d1210-cdb9-50ab-9f1e-ecb9ef12a304$4c510ada-c86b-4815-8820-42cdf82c3d51"
    }
  ]
}

## Upload a file. CAUTION: The target filename need to be passed to the URL, otherwise the upload will fail with a HTTP 500.

curl -X PUT  'https://ocis.example.org/dav/spaces/166d1210-cdb9-50ab-9f1e-ecb9ef12a304$4c510ada-c86b-4815-8820-42cdf82c3d51/testfile.md' -H "Authorization: Bearer $token" --data-binary @/tmp/testfile.md

All in all, this process is more a hack than a stable API interaction.

4 Likes

There was a wrong cookie path used in the authorize curl command. I have fixed it now and improved the URL parameter handling as well.

Is there anything else to be considered? I spend hours on trying to access the webdav api with the bearer token - be it with rclone or with curl as shown by you.

Token generation and the request to the graph api works but when I try to access the webdav api, I get a http code 401 or 404 depending on the webdav url I choose.

With basic auth all works fine.

The Token has a very short Time to live.

Oidc agent is exactly for that purpose, to keep the token refreshed.

Unfortunately OIDC is creating some barrier to use it for machine to machine communication.

Addition regarding the default Idp in ocis Try to ship Authelia as the default IdP in the ocis binary

I forgot to mention that I also configured rclone to work with oidc-agent but had the same problem.