AuthenticatedRequestFactory with BasicAuth

Christof Hurst February 1, 2022

Hi,

actually we are using Jira Server and Confluence Server. To create page structures in Confluence from Jira tickets, we have a script running in a postfunction. That uses the primary link which is actually Confluence Server.

The following example works:

import com.atlassian.applinks.api.ApplicationLink
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.application.confluence.ConfluenceApplicationType
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.sal.api.net.Request

def applicationLinkService = ComponentLocator.getComponent(ApplicationLinkService.class)
ApplicationLink primaryConfluenceLink = applicationLinkService.getPrimaryApplicationLink(ConfluenceApplicationType.class)

def authenticatedRequestFactory = primaryConfluenceLink.createImpersonatingAuthenticatedRequestFactory()

// weiter gehen würde es z.B. mit 
def request = authenticatedRequestFactory
	.createRequest(Request.MethodType.GET, "rest/api/user?username=<USERNAME>")
	.addHeader("Content-Type", "application/json")
String xml_result = request.execute()

When switching to Cloud with Confluence then Confluence Cloud will also be primary link but we can't use the createImpersonatingAuthenticatedRequestFactory() method anymore.

Instead we have to use createAuthenticatedRequestFactory() with a BasicAuth AuthenticationProvider (https://docs.atlassian.com/applinks-api/3.2/com/atlassian/applinks/api/auth/AuthenticationProvider.html)
Actually I have no glue how to do this. Can anybody help with that?

I know there are other methods like UrlConnection or similar. But I want to use this classes.

Thanks for your suggestions.

Christof

1 answer

1 accepted

0 votes
Answer accepted
Christof Hurst February 10, 2022

Simply works with handing over an AuthenticationProvider:

import com.atlassian.applinks.api.ApplicationLink
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.application.confluence.ConfluenceApplicationType
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.sal.api.net.Request
import com.atlassian.applinks.api.auth.types.OAuthAuthenticationProvider

def applicationLinkService = ComponentLocator.getComponent(ApplicationLinkService.class)
ApplicationLink primaryConfluenceLink = applicationLinkService.getPrimaryApplicationLink(ConfluenceApplicationType.class)

def authenticatedRequestFactory = primaryConfluenceLink.createAuthenticatedRequestFactory(OAuthAuthenticationProvider.class)

// call once in case the user has not confirmed yet, c&p the url to browser and confirm
// authenticatedRequestFactory.authorisationURI

def request = authenticatedRequestFactory
.createRequest(Request.MethodType.GET, "rest/api/user/current")
.addHeader("Content-Type", "application/json")
request.execute()

 

Dinesh Dinnu October 11, 2022

Hello Christof,

 

When I try to use the same code which you posted above, I am getting the following exception. I am admin on both confluence and Jira. I have no issues using createImpersonatingAuthenticatedRequestFactory(), but we cannot use that anymore in our organization. Is this something to with the commented code or how do I pass the credentials? Please help me.

// authenticatedRequestFactory.authorisationURI
Message:
com.atlassian.applinks.api.CredentialsRequiredException: You do not have an authorized access token for the remote resource.
Stack:
com.atlassian.applinks.oauth.auth.ThreeLeggedOAuthRequestFactoryImpl.retrieveConsumerToken(ThreeLeggedOAuthRequestFactoryImpl.java:91)
com.atlassian.applinks.oauth.auth.ThreeLeggedOAuthRequestFactoryImpl.createRequest(ThreeLeggedOAuthRequestFactoryImpl.java:84)
com.atlassian.applinks.core.auth.ApplicationLinkRequestFactoryFactoryImpl$AbsoluteURLRequestFactory.createRequest(ApplicationLinkRequestFactoryFactoryImpl.java:193)
com.atlassian.applinks.core.auth.ApplicationLinkAnalyticsRequestFactory.createRequest(ApplicationLinkAnalyticsRequestFactory.java:30)
com.atlassian.applinks.api.ApplicationLinkRequestFactory$createRequest.call(Unknown Source)
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135)
script_068216c11fa5b7dbb7f47c3b598cfa9a.run(script_068216c11fa5b7dbb7f47c3b598cfa9a.groovy:75)
Christof Hurst October 11, 2022

Hi Dinesh,

you must once uncomment the line and return the authorization url in console. Make sure to do this (also) with the user who runs script later.

Then copy and paste the url in a browser and click "Allow" or similar.

After that the script should run.

Like Dinesh Dinnu likes this
Dinesh Dinnu October 12, 2022

Hi Christof,

 

Your response is working perfectly fine, but I am not the system administrator in our production instance. I will have to tell this procedure to our admin for production deployment. So is there a way to provide user name and password token in the AuthHeader something like httpBasicAuthHeader(username, password token) in your code. 


def request = authenticatedRequestFactory
.createRequest(Request.MethodType.GET, "rest/api/user/current")
.addHeader("Content-Type", "application/json")
request.execute()

 

Your help would be greatly appreciated.

Christof Hurst October 12, 2022

Hi,

the main thing is to NOT provide username and passwort. The acting user (normally a technical user) is already logged in and with the url the authentication token is generated and stored in confluence. So confluence "knows" the requesting user already.

It's like a normal user that has to click on "Allow" access when read data from connected confluence inside Jira dashboard e.g. 

BR

Dinesh Dinnu October 12, 2022

Sounds good. Just in case if I want to pass the username and password in the token form, is there a method like httpBasicAuthHeader that can be added in the request?

Thanks for your help!!

Christof Hurst October 12, 2022

I don't know. The alternative was to use 

HttpsURLConnection

But this was a very uncomfortable way. 

Suggest an answer

Log in or Sign up to answer