diff --git a/changelog/unreleased/enhancement-default-link-permissions b/changelog/unreleased/enhancement-default-link-permissions
new file mode 100644
index 00000000000..5bc9670ebad
--- /dev/null
+++ b/changelog/unreleased/enhancement-default-link-permissions
@@ -0,0 +1,6 @@
+Enhancement: Default link permission
+
+When creating a new link, Web now respects the default permissions coming from the server.
+
+https://github.com/owncloud/web/pull/10037
+https://github.com/owncloud/web/issues/9919
diff --git a/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue b/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue
index 54613e111c1..b1921639137 100644
--- a/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue
+++ b/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue
@@ -28,6 +28,7 @@
 import { computed } from 'vue'
 import {
   createQuicklink,
+  getDefaultLinkPermissions,
   showQuickLinkPasswordModal,
   useAbility,
   useClientService,
@@ -37,6 +38,7 @@ import {
 } from '@ownclouders/web-pkg'
 import { Resource } from '@ownclouders/web-client'
 import { useGettext } from 'vue3-gettext'
+import { SharePermissionBit } from '@ownclouders/web-client/src/helpers'
 
 export default {
   setup() {
@@ -88,7 +90,9 @@ export default {
           store.getters.capabilities?.files_sharing?.public?.password?.enforced_for?.read_only ===
           true
 
-        if (passwordEnforced) {
+        const permissions = getDefaultLinkPermissions({ ability, store })
+
+        if (passwordEnforced && permissions > SharePermissionBit.Internal) {
           showQuickLinkPasswordModal(
             { store, $gettext: language.$gettext, passwordPolicyService },
             async (password) => {
diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
index 47d4903308d..dc17fcd2f45 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
@@ -122,7 +122,8 @@ import {
   useCapabilityFilesSharingPublicCanContribute,
   useCapabilityFilesSharingPublicAlias,
   useAbility,
-  usePasswordPolicyService
+  usePasswordPolicyService,
+  getDefaultLinkPermissions
 } from '@ownclouders/web-pkg'
 import { shareViaLinkHelp, shareViaIndirectLinkHelp } from '../../../helpers/contextualHelpers'
 import {
@@ -219,6 +220,7 @@ export default defineComponent({
 
     return {
       $store: store,
+      ability,
       space,
       resource,
       incomingParentShare: inject<Share>('incomingParentShare'),
@@ -417,7 +419,10 @@ export default defineComponent({
       this.checkLinkToCreate({
         link: {
           name: this.$gettext('Link'),
-          permissions: this.canCreatePublicLinks ? 1 : 0,
+          permissions: getDefaultLinkPermissions({
+            ability: this.ability,
+            store: this.$store
+          }).toString(),
           expiration: this.expirationDate.default,
           password: false
         }
diff --git a/packages/web-app-files/src/components/SideBar/Shares/Links/CreateQuickLink.vue b/packages/web-app-files/src/components/SideBar/Shares/Links/CreateQuickLink.vue
index d1d2a5ab7b2..133fc766b2e 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/Links/CreateQuickLink.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/Links/CreateQuickLink.vue
@@ -26,22 +26,9 @@
 </template>
 
 <script lang="ts">
-import { computed, defineComponent, inject, unref } from 'vue'
-import {
-  useAbility,
-  useCapabilityFilesSharingPublicAlias,
-  useCapabilityFilesSharingPublicCanContribute,
-  useCapabilityFilesSharingPublicCanEdit,
-  useCapabilityFilesSharingQuickLinkDefaultRole,
-  useCapabilityFilesSharingResharing
-} from '@ownclouders/web-pkg'
-import { Resource } from '@ownclouders/web-client/src'
+import { defineComponent } from 'vue'
+import { useAbility, getDefaultLinkPermissions, useStore } from '@ownclouders/web-pkg'
 import { useGettext } from 'vue3-gettext'
-import {
-  LinkShareRoles,
-  linkRoleInternalFolder,
-  linkRoleViewerFolder
-} from '@ownclouders/web-client/src/helpers/share'
 
 export default defineComponent({
   name: 'CreateQuickLink',
@@ -54,32 +41,15 @@ export default defineComponent({
   },
   emits: ['createPublicLink'],
   setup(props, { emit }) {
-    const { can } = useAbility()
+    const store = useStore()
+    const ability = useAbility()
     const { $gettext } = useGettext()
 
-    const canCreatePublicLinks = computed(() => can('create-all', 'PublicLink'))
-    const resource = inject<Resource>('resource')
-    const allowResharing = useCapabilityFilesSharingResharing()
-    const canEdit = useCapabilityFilesSharingPublicCanEdit()
-    const canContribute = useCapabilityFilesSharingPublicCanContribute()
-    const alias = useCapabilityFilesSharingPublicAlias()
-    const capabilitiesRoleName = useCapabilityFilesSharingQuickLinkDefaultRole()
     const createQuickLink = () => {
-      const roleName = !unref(canCreatePublicLinks)
-        ? linkRoleInternalFolder.name
-        : unref(capabilitiesRoleName) || linkRoleViewerFolder.name
       const emitData = {
         link: {
           name: $gettext('Link'),
-          permissions: LinkShareRoles.getByName(
-            roleName,
-            unref(resource).isFolder,
-            unref(canEdit),
-            unref(canContribute),
-            unref(alias)
-          )
-            .bitmask(unref(allowResharing))
-            .toString(),
+          permissions: getDefaultLinkPermissions({ ability, store }).toString(),
           expiration: props.expirationDate.enforced ? props.expirationDate.default : null,
           quicklink: true,
           password: false
diff --git a/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts b/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts
index 68a6e1bf19d..e6fb202b862 100644
--- a/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts
+++ b/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts
@@ -5,13 +5,16 @@ import {
   shallowMount
 } from 'web-test-helpers'
 import EmbedActions from 'web-app-files/src/components/EmbedActions/EmbedActions.vue'
+import { getDefaultLinkPermissions } from '@ownclouders/web-pkg'
+import { SharePermissionBit } from '@ownclouders/web-client/src/helpers'
 
 jest.mock('@ownclouders/web-pkg', () => ({
   ...jest.requireActual('@ownclouders/web-pkg'),
   createQuicklink: jest.fn().mockImplementation(({ resource, password }) => ({
     url: (password ? password + '-' : '') + 'link-' + resource.id
   })),
-  showQuickLinkPasswordModal: jest.fn().mockImplementation((_options, cb) => cb('password'))
+  showQuickLinkPasswordModal: jest.fn().mockImplementation((_options, cb) => cb('password')),
+  getDefaultLinkPermissions: jest.fn()
 }))
 
 const selectors = Object.freeze({
@@ -192,6 +195,7 @@ describe('EmbedActions', () => {
       const { wrapper } = getWrapper({
         selectedFiles: [{ id: 1 }],
         abilities: [{ action: 'create-all', subject: 'PublicLink' }],
+        defaultLinkPermissions: SharePermissionBit.Read,
         capabilities: jest.fn().mockReturnValue({
           files_sharing: { public: { password: { enforced_for: { read_only: true } } } }
         })
@@ -245,13 +249,15 @@ function getWrapper(
     abilities = [],
     capabilities = jest.fn().mockReturnValue({}),
     configuration = { options: {} },
-    currentFolder = {}
+    currentFolder = {},
+    defaultLinkPermissions = SharePermissionBit.Internal
   } = {
     selectedFiles: [],
     abilities: [],
     capabilities: jest.fn().mockReturnValue({})
   }
 ) {
+  jest.mocked(getDefaultLinkPermissions).mockReturnValue(defaultLinkPermissions)
   const storeOptions = {
     ...defaultStoreMockOptions,
     getters: {
diff --git a/packages/web-app-files/tests/unit/components/SideBar/Shares/FileLinks.spec.ts b/packages/web-app-files/tests/unit/components/SideBar/Shares/FileLinks.spec.ts
index ae8156af497..0f3eb48a5e2 100644
--- a/packages/web-app-files/tests/unit/components/SideBar/Shares/FileLinks.spec.ts
+++ b/packages/web-app-files/tests/unit/components/SideBar/Shares/FileLinks.spec.ts
@@ -7,8 +7,9 @@ import {
 } from 'web-test-helpers'
 import { mockDeep } from 'jest-mock-extended'
 import { Resource } from '@ownclouders/web-client'
-import { SharePermissions } from '@ownclouders/web-client/src/helpers/share'
+import { SharePermissionBit, SharePermissions } from '@ownclouders/web-client/src/helpers/share'
 import { AbilityRule } from '@ownclouders/web-client/src/helpers/resource/types'
+import { getDefaultLinkPermissions } from '@ownclouders/web-pkg'
 
 const defaultLinksList = [
   {
@@ -38,6 +39,11 @@ const selectors = {
 const linkListItemNameAndCopy = 'name-and-copy-stub'
 const linkListItemDetailsAndEdit = 'details-and-edit-stub'
 
+jest.mock('@ownclouders/web-pkg', () => ({
+  ...jest.requireActual('@ownclouders/web-pkg'),
+  getDefaultLinkPermissions: jest.fn()
+}))
+
 describe('FileLinks', () => {
   describe('links', () => {
     describe('when links list is not empty', () => {
@@ -143,31 +149,39 @@ describe('FileLinks', () => {
       expect(availableRoleOptions[0].permissions()).toEqual([SharePermissions.internal])
       expect(isModifiable).toBeTruthy()
     })
-    it('creates new links with permission 0', async () => {
-      const { wrapper, storeOptions } = getWrapper({ abilities: [] })
-      await wrapper.find(selectors.linkAddButton).trigger('click')
-      expect(storeOptions.modules.Files.actions.addLink).toHaveBeenCalledTimes(1)
-      expect(storeOptions.modules.Files.actions.addLink).toHaveBeenCalledWith(
-        expect.anything(),
-        expect.objectContaining({
-          params: expect.objectContaining({
-            permissions: '0'
+  })
+  describe('new links', () => {
+    it.each([SharePermissionBit.Internal, SharePermissionBit.Read])(
+      'creates new links according to the default link permissions',
+      async (defaultLinkPermissions) => {
+        const { wrapper, storeOptions } = getWrapper({ abilities: [], defaultLinkPermissions })
+        await wrapper.find(selectors.linkAddButton).trigger('click')
+        expect(storeOptions.modules.Files.actions.addLink).toHaveBeenCalledTimes(1)
+        expect(storeOptions.modules.Files.actions.addLink).toHaveBeenCalledWith(
+          expect.anything(),
+          expect.objectContaining({
+            params: expect.objectContaining({
+              permissions: defaultLinkPermissions.toString()
+            })
           })
-        })
-      )
-    })
+        )
+      }
+    )
   })
 })
 
 function getWrapper({
   resource = mockDeep<Resource>({ isFolder: false, canShare: () => true }),
   links = defaultLinksList,
-  abilities = [{ action: 'create-all', subject: 'PublicLink' }]
+  abilities = [{ action: 'create-all', subject: 'PublicLink' }],
+  defaultLinkPermissions = 0
 }: {
   resource?: Resource
   links?: typeof defaultLinksList
   abilities?: AbilityRule[]
+  defaultLinkPermissions?: number
 } = {}) {
+  jest.mocked(getDefaultLinkPermissions).mockReturnValue(defaultLinkPermissions)
   const storeOptions = {
     ...defaultStoreMockOptions,
     getters: {
diff --git a/packages/web-pkg/src/composables/capability/useCapability.ts b/packages/web-pkg/src/composables/capability/useCapability.ts
index 332e3ab4df1..b82aeba37c3 100644
--- a/packages/web-pkg/src/composables/capability/useCapability.ts
+++ b/packages/web-pkg/src/composables/capability/useCapability.ts
@@ -8,6 +8,7 @@ import {
   MediaTypeCapability,
   PasswordPolicyCapability
 } from '@ownclouders/web-client/src/ocs/capabilities'
+import { SharePermissionBit } from '@ownclouders/web-client/src/helpers'
 
 export const useCapability = <T>(
   store: Store<any>,
@@ -39,10 +40,6 @@ export const useCapabilityGraphPersonalDataExport = createCapabilityComposable(
   'graph.personal-data-export',
   false
 )
-export const useCapabilityFilesSharingQuickLinkDefaultRole = createCapabilityComposable(
-  'files_sharing.quick_link.default_role',
-  'viewer'
-)
 export const useCapabilityFilesSharingResharing = createCapabilityComposable(
   'files_sharing.resharing',
   true
@@ -136,6 +133,10 @@ export const useCapabilityFilesSharingPublicAlias = createCapabilityComposable(
   'files_sharing.public.alias',
   false
 )
+export const useCapabilityFilesSharingPublicDefaultPermissions = createCapabilityComposable(
+  'files_sharing.public.default_permissions',
+  SharePermissionBit.Read
+)
 export const useCapabilityNotifications = createCapabilityComposable(
   'notifications.ocs-endpoints',
   []
diff --git a/packages/web-pkg/src/helpers/share/link.ts b/packages/web-pkg/src/helpers/share/link.ts
index 88050dc7778..7d8b01ccae1 100644
--- a/packages/web-pkg/src/helpers/share/link.ts
+++ b/packages/web-pkg/src/helpers/share/link.ts
@@ -1,11 +1,9 @@
 import { DateTime } from 'luxon'
 import {
-  LinkShareRoles,
   Share,
-  linkRoleInternalFolder,
-  linkRoleViewerFolder,
   ShareTypes,
-  buildShare
+  buildShare,
+  SharePermissionBit
 } from '@ownclouders/web-client/src/helpers/share'
 import { Store } from 'vuex'
 import { ClientService, PasswordPolicyService } from '../../services'
@@ -39,7 +37,7 @@ export interface CopyQuickLink extends CreateQuicklink {
 // it has a fallback to the vue-use implementation.
 //
 // https://webkit.org/blog/10855/
-const copyToClipboard = async (quickLinkUrl: string) => {
+const copyToClipboard = (quickLinkUrl: string) => {
   if (typeof ClipboardItem && navigator?.clipboard?.write) {
     return navigator.clipboard.write([
       new ClipboardItem({
@@ -52,7 +50,7 @@ const copyToClipboard = async (quickLinkUrl: string) => {
   }
 }
 export const copyQuicklink = async (args: CopyQuickLink) => {
-  const { store, language, resource, clientService, passwordPolicyService } = args
+  const { ability, store, language, resource, clientService, passwordPolicyService } = args
   const { $gettext } = language
 
   const linkSharesForResource = await clientService.owncloudSdk.shares.getShares(resource.path, {
@@ -82,7 +80,9 @@ export const copyQuicklink = async (args: CopyQuickLink) => {
   const isPasswordEnforced =
     store.getters.capabilities?.files_sharing?.public?.password?.enforced_for?.read_only === true
 
-  if (unref(isPasswordEnforced)) {
+  const permissions = getDefaultLinkPermissions({ ability, store })
+
+  if (unref(isPasswordEnforced) && permissions > SharePermissionBit.Internal) {
     return showQuickLinkPasswordModal(
       { $gettext, store, passwordPolicyService },
       async (password: string) => {
@@ -125,33 +125,13 @@ export const copyQuicklink = async (args: CopyQuickLink) => {
   }
 }
 
-export const createQuicklink = async (args: CreateQuicklink): Promise<Share> => {
+export const createQuicklink = (args: CreateQuicklink): Promise<Share> => {
   const { clientService, resource, store, password, language, ability } = args
   const { $gettext } = language
 
-  const canCreatePublicLink = ability.can('create-all', 'PublicLink')
-  const allowResharing = store.state.user.capabilities.files_sharing?.resharing
-  const capabilitiesRoleName =
-    store.state.user.capabilities.files_sharing?.quick_link?.default_role ||
-    linkRoleViewerFolder.name
-  const canEdit = store.state.user.capabilities.files_sharing?.public?.can_edit || false
-  const canContribute = store.state.user.capabilities.files_sharing?.public?.can_contribute || false
-  const alias = store.state.user.capabilities.files_sharing?.public?.alias
-  const roleName = !canCreatePublicLink
-    ? linkRoleInternalFolder.name
-    : capabilitiesRoleName || linkRoleViewerFolder.name
-  const permissions = LinkShareRoles.getByName(
-    roleName,
-    resource.isFolder,
-    canEdit,
-    canContribute,
-    alias
-  ).bitmask(allowResharing)
-  const params: {
-    [key: string]: unknown
-  } = {
+  const params: Record<string, unknown> = {
     name: $gettext('Link'),
-    permissions: permissions.toString(),
+    permissions: getDefaultLinkPermissions({ ability, store }).toString(),
     quicklink: true
   }
 
@@ -180,3 +160,24 @@ export const createQuicklink = async (args: CreateQuicklink): Promise<Share> =>
     storageId: resource.fileId || resource.id
   })
 }
+
+export const getDefaultLinkPermissions = ({
+  ability,
+  store
+}: {
+  ability: Ability
+  store: Store<any>
+}) => {
+  const canCreatePublicLink = ability.can('create-all', 'PublicLink')
+  if (!canCreatePublicLink) {
+    return SharePermissionBit.Internal
+  }
+
+  let defaultPermissions: number =
+    store.state.user.capabilities.files_sharing?.public?.default_permissions
+  if (defaultPermissions === undefined) {
+    defaultPermissions = SharePermissionBit.Read
+  }
+
+  return defaultPermissions
+}
diff --git a/packages/web-pkg/tests/unit/helpers/share/link.spec.ts b/packages/web-pkg/tests/unit/helpers/share/link.spec.ts
index 65fee84f516..68b790c6c27 100644
--- a/packages/web-pkg/tests/unit/helpers/share/link.spec.ts
+++ b/packages/web-pkg/tests/unit/helpers/share/link.spec.ts
@@ -1,4 +1,9 @@
-import { copyQuicklink, createQuicklink, CreateQuicklink } from '../../../../src/helpers/share'
+import {
+  copyQuicklink,
+  createQuicklink,
+  CreateQuicklink,
+  getDefaultLinkPermissions
+} from '../../../../src/helpers/share'
 import { DateTime } from 'luxon'
 import { Store } from 'vuex'
 import { ClientService, PasswordPolicyService } from '../../../../src/services'
@@ -7,6 +12,7 @@ import { Ability } from '@ownclouders/web-client/src/helpers/resource/types'
 import { mock, mockDeep } from 'jest-mock-extended'
 import { Language } from 'vue3-gettext'
 import { Resource } from '@ownclouders/web-client'
+import { SharePermissionBit } from '@ownclouders/web-client/src/helpers'
 
 jest.mock('@vueuse/core', () => ({
   useClipboard: jest.fn().mockReturnValue({ copy: jest.fn() })
@@ -17,6 +23,7 @@ const mockStore = {
     capabilities: {
       files_sharing: {
         public: {
+          default_permissions: 1,
           password: {
             enforced_for: {
               read_only: false
@@ -30,10 +37,8 @@ const mockStore = {
     user: {
       capabilities: {
         files_sharing: {
-          quickLink: {
-            default_role: 'viewer'
-          },
           public: {
+            default_permissions: 1,
             expire_date: {
               enforced: true,
               days: 5
@@ -60,6 +65,7 @@ const getAbilityMock = (hasPermission) => mock<Ability>({ can: () => hasPermissi
 
 let returnBitmask = 1
 jest.mock('@ownclouders/web-client/src/helpers/share', () => ({
+  ...jest.requireActual('@ownclouders/web-client/src/helpers/share'),
   LinkShareRoles: {
     getByName: jest.fn().mockReturnValue({ bitmask: jest.fn(() => returnBitmask) })
   },
@@ -114,7 +120,7 @@ describe('createQuicklink', () => {
       clientService.owncloudSdk.shares.getShares.mockResolvedValue([])
       const passwordPolicyService = mockDeep<PasswordPolicyService>()
       returnBitmask = role === 'viewer' ? 1 : 0
-      mockStore.state.user.capabilities.files_sharing.quickLink.default_role = role
+      mockStore.state.user.capabilities.files_sharing.public.default_permissions = returnBitmask
 
       const args: CreateQuicklink = {
         store: mockStore as unknown as Store<any>,
@@ -151,3 +157,32 @@ describe('createQuicklink', () => {
     }
   )
 })
+
+describe('getDefaultLinkPermissions', () => {
+  it('returns internal if user is not allowed to create public links', () => {
+    const permissions = getDefaultLinkPermissions({
+      ability: mock<Ability>({ can: () => false }),
+      store: mockStore as any
+    })
+    expect(permissions).toBe(SharePermissionBit.Internal)
+  })
+  it.each([SharePermissionBit.Internal, SharePermissionBit.Read])(
+    'returns the defined default permissions from the capabilities if user is allowed to create public links',
+    (defaultPermissions) => {
+      const store = {
+        state: {
+          user: {
+            capabilities: {
+              files_sharing: { public: { default_permissions: defaultPermissions } }
+            }
+          }
+        }
+      }
+      const permissions = getDefaultLinkPermissions({
+        ability: mock<Ability>({ can: () => true }),
+        store: store as any
+      })
+      expect(permissions).toBe(defaultPermissions)
+    }
+  )
+})