Featured image of post URI/URL & Deep Linking to Workspace One Application Panes

URI/URL & Deep Linking to Workspace One Application Panes

Munki and JAMF both support linking to URI referencing options. Workspace One has struggled with this, until now..

Introduction

One of the major conveniences about Munki and JAMF are that they support linking to items within the service. One major issue with Workspace One is that this is not possible or at least, until now with this hacky workaround.

At Epidemic Sound, we opted to use the native toolset of WS1 rather than doubling up on both Intelligent Hub and custom open source toolsets (though we are not opposed to opening up our toolset range in the future).

The Idea

I live in a world where I like to make things very easy for people. If we give them a document, they should be able to click one button to do all the actions, especially if that action exists in Intelligent Hub. However, there was no URL schema that I could find in the macOS Device Management Workspace One Guide, or if you Google Search the entire VMware website.

This makes my life difficult to point people to the proper place without having to do step by step guides.

Well…. here comes a hacky solution and a feature request.

The Research

When looking through strings that Workspace One uses, we can find the following:

1
2
awjade://
awws1://

If we take the first and recursively grep through the entire folder path of Workspace One Intelligent Hub:

1
2
3
4
5
andrew@Andrews-MacBook-Pro-2 Contents % pwd
/Applications/Workspace ONE Intelligent Hub.app/Contents
andrew@Andrews-MacBook-Pro-2 Contents % grep "awjade://" -R *
Binary file PlugIns/HubPreviewExtension.appex/Contents/MacOS/HubPreviewExtension matches
Binary file Resources/SSOHelper.app/Contents/MacOS/SSOHelper matches

So lets dive further into the file and see where it pulls up using grep to start with:

1
2
3
4
5
6
7
8
% grep -a --color -A 2 -B 2 --binary-files=text "awjade" PlugIns/HubPreviewExtension.appex/Contents/MacOS/HubPreviewExtension
��������0���__C�`����|�������81�,����H���e����1A�������1m�������L����t����1}����������}p���]����]����]�����1HubPreviewExtensionAppNetworkHandlerP������������

_TtC19HubPreviewExtension21PreviewViewController@16@0:8v24@0:8@16v16@0:8v40@0:8@16@24@?32@32@0:8@16@24@24@0:8@16appIconappTitleappDescriptionappCategoryappOpenButtonspinnerratingValueLabelratingStarStackhorizontalSeparator1horizontalSeparator2horizontalSeparator3entitlementlaunchTimerisLoadingAppT@"NSImageView",N,W,VappIconT@"NSTextField",N,W,VappTitleT@"NSTextField",N,W,VappDescriptionT@"NSTextField",N,W,VappCategoryT@"NSButton",N,W,VappOpenButtonT@"NSProgressIndicator",N,W,VspinnerT@"NSTextField",N,W,VratingValueLabelT@"NSStackView",N,W,VratingStarStackT@"NSBox",N,W,VhorizontalSeparator1T@"NSBox",N,W,VhorizontalSeparator2T@"NSBox",N,W,VhorizontalSeparator3nibNameT@"NSString",N,RSomething went wrong: entitlement/app metadata missing in spotlight preview extensionv16@?0@"NSTimer"8OTA call did not respond in pre-determined time, so launched hub mac appawjade://appIdentifier-Successfully launched appApp launch from spotlight preview failed, redirecting to launch in app : %{public}@Error: %{public}@
No entitlement found with identifier : %{public}@QLPreviewingControllerv32@0:8@16@?24v40@0:8@"NSString"16@"NSString"24@?<v@?@"NSError">32v32@0:8@"NSURL"16@?<v@?@"NSError">24NSObjectc24@0:8@16q16@0:8#16@0:8@24@0:8:16@32@0:8:16@24@40@0:8:16@24@32c16@0:8c24@0:8#16c24@0:8:16Vv16@0:8Q16@0:8^{_NSZone=}16@0:8hashTq,N,RsuperclassT#,N,RdescriptiondebugDescriptionc24@0:8@"Protocol"16@"NSString"16@0:8_TtC19HubPreviewExtension17AppNetworkHandlerUnable to launch app %{public}@ due to missing or invalid launchLinkUnable to launch app: %{public}@ due to missing or invalid launchLinkUnable to launch app:  %{public}@. due to invalid URL %{public}@.Launching app - %{public}@ - after successfully retrieving OTA token: %{public}@Opening URL: %{public}@Unable to open url:  %{public}@. Relaying error to user.appIconsetAppIcon:appTitlesetAppTitle:appDescriptionsetAppDescription:appCategorysetAppCategory:appOpenButtonsetAppOpenButton:spinnersetSpinner:ratingValueLabelsetRatingValueLabel:ratingStarStacksetRatingStarStack:horizontalSeparator1setHorizontalSeparator1:horizontalSeparator2setHorizontalSeparator2:horizontalSeparator3setHorizontalSeparator3:nibNameloadViewviewWillAppearpreparePreviewOfSearchableItemWithIdentifier:queryString:completionHandler:appOpenAction:initWithNibName:bundle:initWithCoder:.cxx_destructarrangedSubviewstagimageNamed:setImage:scheduledTimerWithTimeInterval:repeats:block:invalidateidentifiersharedWorkspaceopenURLs:withAppBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifiers:setHidden:isHiddenstopAnimation:startAnimation:vieweffectiveAppearancebestMatchFromAppearancesWithNames:appearanceNamed:setAppearance:initWithKey:ascending:performFetch:setStringValue:summarynameinitWithContentsOfFile:deallocpreparePreviewOfFileAtURL:completionHandler:isEqual:hashsuperclassclassselfperformSelector:performSelector:withObject:performSelector:withObject:withObject:isProxyisKindOfClass:isMemberOfClass:conformsToProtocol:respondsToSelector:retainreleaseautoreleaseretainCountzonedescriptiondebugDescriptionopenURL:So16NSViewControllerC����So11NSImageViewCSgXwSo11NSTextFieldCSgXwSo8NSButtonCSgXwSo19NSProgressIndicatorCSgXwSo11NSStackViewCSgXwSo5NSBoxCSgXw/SgSo7NSTimerCSgSb5���SgXw+���SgXwz_Xx��Sg�y�G�y�_pG�y����G�ySo16NSSortDescriptorCG����So8NSStringCSS$sSY������6����n���$ss21_ObjectiveCBridgeableP/���)���XMTC_pSgIegg_KySSSg)_pGIegg_�Sg�y�GappIconappTitleappDescriptionappCategoryappOpenButtonspinnerratingValueLabelratingStarStackhorizontalSeparator1horizontalSeparator2horizontalSeparator3entitlementlaunchTimerisLoadingApp_rawValueRawValue_ObjectiveCType"�����

_TtC19HubPreviewExtension21PreviewViewController@16@0:8v24@0:8@16v16@0:8v40@0:8@16@24@?32@32@0:8@16@24@24@0:8@16appIconappTitleappDescriptionappCategoryappOpenButtonspinnerratingValueLabelratingStarStackhorizontalSeparator1horizontalSeparator2horizontalSeparator3entitlementlaunchTimerisLoadingAppT@"NSImageView",N,W,VappIconT@"NSTextField",N,W,VappTitleT@"NSTextField",N,W,VappDescriptionT@"NSTextField",N,W,VappCategoryT@"NSButton",N,W,VappOpenButtonT@"NSProgressIndicator",N,W,VspinnerT@"NSTextField",N,W,VratingValueLabelT@"NSStackView",N,W,VratingStarStackT@"NSBox",N,W,VhorizontalSeparator1T@"NSBox",N,W,VhorizontalSeparator2T@"NSBox",N,W,VhorizontalSeparator3nibNameT@"NSString",N,RSomething went wrong: entitlement/app metadata missing in spotlight preview extensionv16@?0@"NSTimer"8OTA call did not respond in pre-determined time, so launched hub mac appawjade://appIdentifier-Successfully launched appApp launch from spotlight preview failed, redirecting to launch in app : %{public}@Error: %{public}@
No entitlement found with identifier : %{public}@QLPreviewingControllerv32@0:8@16@?24v40@0:8@"NSString"16@"NSString"24@?<v@?@"NSError">32v32@0:8@"NSURL"16@?<v@?@"NSError">24NSObjectB24@0:8@16q16@0:8#16@0:8@24@0:8:16@32@0:8:16@24@40@0:8:16@24@32B16@0:8B24@0:8#16B24@0:8:16Vv16@0:8Q16@0:8^{_NSZone=}16@0:8hashTq,N,RsuperclassT#,N,RdescriptiondebugDescriptionB24@0:8@"Protocol"16@"NSString"16@0:8_TtC19HubPreviewExtension17AppNetworkHandlerUnable to launch app %{public}@ due to missing or invalid launchLinkUnable to launch app: %{public}@ due to missing or invalid launchLinkUnable to launch app:  %{public}@. due to invalid URL %{public}@.Launching app - %{public}@ - after successfully retrieving OTA token: %{public}@Unable to open url:  %{public}@. Relaying error to user.Opening URL: %{public}@appIconsetAppIcon:appTitlesetAppTitle:appDescriptionsetAppDescription:appCategorysetAppCategory:appOpenButtonsetAppOpenButton:spinnersetSpinner:ratingValueLabelsetRatingValueLabel:ratingStarStacksetRatingStarStack:horizontalSeparator1setHorizontalSeparator1:horizontalSeparator2setHorizontalSeparator2:horizontalSeparator3setHorizontalSeparator3:nibNameloadViewviewWillAppearpreparePreviewOfSearchableItemWithIdentifier:queryString:completionHandler:appOpenAction:initWithNibName:bundle:initWithCoder:.cxx_destructarrangedSubviewstagimageNamed:setImage:scheduledTimerWithTimeInterval:repeats:block:invalidateidentifiersharedWorkspaceopenURLs:withAppBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifiers:setHidden:isHiddenstartAnimation:stopAnimation:vieweffectiveAppearancebestMatchFromAppearancesWithNames:appearanceNamed:setAppearance:initWithKey:ascending:performFetch:setStringValue:summarynameinitWithContentsOfFile:deallocpreparePreviewOfFileAtURL:completionHandler:isEqual:hashsuperclassclassselfperformSelector:performSelector:withObject:performSelector:withObject:withObject:isProxyisKindOfClass:isMemberOfClass:conformsToProtocol:respondsToSelector:retainreleaseautoreleaseretainCountzonedescriptiondebugDescriptionopenURL:So16NSViewControllerC����So11NSImageViewCSgXwSo11NSTextFieldCSgXwSo8NSButtonCSgXwSo19NSProgressIndicatorCSgXwSo11NSStackViewCSgXwSo5NSBoxCSgXw    SgSo7NSTimerCSgSb7���SgXw-���SgXwz_Xx��Sy�y_pG�y����G�ySo16NSSortDescriptorCG����So8NSStringCSS$sSY����������D���$ss21_ObjectiveCBridgeableP1���+���XMTm_pSgIegg_uySSSgS_pGIegg_�Sg5y�GappIconappTitleappDescriptionappCategoryappOpenButtonspinnerratingValueLabelratingStarStackhorizontalSeparator1horizontalSeparator2horizontalSeparator3entitlementlaunchTimerisLoadingApp_rawValueRawValue_ObjectiveCType0������

So now that we see awjade://, we now have a URL:

1
2
3
4
5
6
Something went wrong: entitlement/app metadata missing in spotlight preview extension
v16@?0@"NSTimer"8
OTA call did not respond in pre-determined time, so launched hub mac app
awjade://appIdentifier-
Successfully launched app
App launch from spotlight preview failed, redirecting to launch in app

This awjade://appIdentifier- looks interesting.

From here we have two methods to obtain the rest of the information:

Web proxy

  1. Install a web proxy (Fiddler, Charles, BurpSuite, OWASP ZAP, or some other tool)
  2. Install the SSL Cert so that you can inspect secure traffic being passed through the proxy.
  3. Search for the URL that looks something like this: https://TENANTID.vmwareidentity.de/catalog-portal/services/api/v3/hubLanding?excludeThinApps=true&includeEntitlements=true&refreshCache=true

This should return a JSON body that looks something similar to this:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
{
    "areAllEntitlementsLoaded": true,
    "allProfilesLoaded": false,
    "loadFromDbFailed": false,
    "deviceInfo": {
        "deviceStatus": "MDM_DEVICE_FULLY_ENROLLED"
    },
    "entitlements": {
        "Okta-UUID-SAML_2_0": {
            "subType": "OKTASAML20",
            "version": "",
            "installStatus": "ACTIVATED",
            "beta": false,
            "visible": true,
            "mdmManagedAutoDeployed": false,
            "approvalRequired": false,
            "justificationRequiredForAppApproval": false,
            "mgmtRequired": false,
            "useAirwatchBrowser": false,
            "appId": "Okta-UUID-SAML_2_0",
            "favorite": false,
            "launchUrl": "https://TENANTID.vmwareidentity.de/SAAS/API/1.0/GET/apps/launch/thirdPartyAppLaunch?appType=OKTA&targetUrl=https://TENANTID.okta.com/home/APP/OMIT/19411",
            "optionalAppInfo": {
                "usePerAppPassword": false
            },
            "price": null,
            "perDeviceActivationRequired": false,
            "approvalRequiredForMdmApp": false,
            "thinappPackage": false,
            "thinapp": false,
            "name": "APP",
            "type": "OKTA",
            "size": 0,
            "links": [
                {
                    "rel": "launch",
                    "href": "https://TENANTID.vmwareidentity.de/SAAS/API/1.0/GET/apps/launch/thirdPartyAppLaunch?appType=OKTA&targetUrl=https://TENANTID.okta.com/home/APP/OMIT/19411"
                },
                {
                    "rel": "icon",
                    "href": "https://ok11static.oktacdn.com/fs/bcg/4/OMIT"
                },
                {
                    "rel": "install",
                    "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/activate/Okta-UUID-SAML_2_0"
                },
                {
                    "rel": "appDetails",
                    "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/apps/Okta-UUID-SAML_2_0"
                },
                {
                    "rel": "favorites",
                    "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/favorites/Okta-UUID-SAML_2_0?favorite={boolValue}"
                }
            ]
        },
        "MDM-4868-Native-Internal": {
            "subType": "INTERNAL",
            "version": "4.19.0",
            "installStatus": "ACTIVATED",
            "beta": false,
            "visible": true,
            "mdmManagedAutoDeployed": false,
            "approvalRequired": false,
            "bundleId": "com.vmw.macos.APP",
            "justificationRequiredForAppApproval": false,
            "versionHash": "AC6DE73D95CB02076D54E5DBCA5B35B9F26BF303",
            "packageFamilyName": "",
            "mgmtRequired": false,
            "useAirwatchBrowser": false,
            "appId": "MDM-4868-Native-Internal",
            "installMessage": "The app will download automatically and install on your device.",
            "favorite": false,
            "launchUrl": "",
            "optionalAppInfo": {
                "usePerAppPassword": false
            },
            "price": null,
            "perDeviceActivationRequired": false,
            "approvalRequiredForMdmApp": false,
            "thinappPackage": false,
            "thinapp": false,
            "name": "APP",
            "type": "NATIVE",
            "size": 151603086,
            "links": [
                {
                    "rel": "icon",
                    "href": "https://ds1678.awmdm.com/Catalog/publicblob/9442ecd1-7d82-4ad8-a8f2-d0f5a1599c1e/BlobHandler.pblob"
                },
                {
                    "rel": "install",
                    "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/activate/MDM-4868-Native-Internal"
                },
                {
                    "rel": "appDetails",
                    "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/apps/MDM-4868-Native-Internal"
                },
                {
                    "rel": "favorites",
                    "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/favorites/MDM-4868-Native-Internal?favorite={boolValue}"
                }
            ]
        }
    },
    (Omitting some lines)
    "userIdMismatch": false,
    "bookmarkOrderSet": false,
    "links": [
        {
            "rel": "self",
            "href": "https://TENANTID.vmwareidentity.de:443/catalog-portal/services/api/v3/hubLanding?excludeThinApps=true&includeEntitlements=true&refreshCache=true"
        }
    ]
}

All of the items listed here, are what you would append to awjade://appIdentifider- to load Intelligent Hub.

1
2
3
4
5
6
"entitlements": {
        "Okta-UUID-SAML_2_0": {
        }
        "MDM-4868-Native-Internal": {
        }
}

sqlite method

If not already installed, install sqlite3

  1. Open up the sqlite3 client towards ~/Library/Group Containers/group.com.vmware.hub.mac/IntelligentHub/GreenClient.sqlite
  2. If you don’t already have headers on, run .headers ON (mainly for convenience)
  3. Run .tables, this should output something similar to the following
1
2
3
4
5
sqlite> .tables
ZBRANDINGVALUE        ZETAG                 Z_MODELCACHE
ZCATALOGLAYOUTSORT    ZMOBILEFLOWCONNECTOR  Z_PRIMARYKEY
ZCONTENT              ZTENANTCUSTOMIZATION
ZENDPOINT             Z_METADATA
  1. Run select ZNAME,ZIDENTIFIERfrom ZCONTENT;, this should output something similar to:
1
2
3
4
5
6
select ZIDENTIFIER,ZNAME from ZCONTENT;
ZIDENTIFIER|ZNAME
OKTA-OMIT-Okta-SAML_2_0|Google Workspace Drive
Favorites|Favorites
MDM-OMIT-Native-Internal|osquery
OKTA-OMIT-Okta-BOOKMARK|Apple (eCommerce)

What you want is the entire item where the item you want to link from ZNAME is listed in the column ZIDENTIFIER.

The Solution

From here, now you have the identifiers that you can obtain from locally on the device or via the network.

Now all that needs to happen is:

awjade://appIdentifier-OKTA-OMIT-Okta-SAML_2_0

awjade://appIdentifier-MDM-OMIT-Native-Internal

You can launch a user directly into an application pane in Intelligent Hub.

Unfortunately, this does not work with Favorites, or other types of entries that are listed here. I am sure there is another way around this.

None of this has been tested on Windows, however, I don’t have any reason to believe this would not also work on that platform.

Workspace One Ideas

You can find a feature request / improvement on Workspace One here:

https://wsone.ideas.aha.io/ideas/UEMCPI-I-1246

The hope is that Workspace One properly implements this, rather than us hacking around to find a way to make this work. Ideally, an admin should have be able to link something like:

awjade://app/Google-Chrome

awjade://self-service

This would allow administrators a more readable way to deep link, and potentially easier to determine a naming scheme from rather than random numbers.

You can see the comments at the time of writing in the attached PDF.

comments powered by Disqus
Thanks for stopping by!
Built with Hugo