Hi, I'm trying to get the image file data (not just the URL) for a member's avatar. The URL returned the a user's avatarUrls along the lines of:
https://avatar-cdn.atlassian.com/xxxxyyyyzzz?s=24&d=https://mydomain.atlassian.net/secure/useravatar?size=small&ownerId=my.acct&avatarId=12345&noRedirect=true
The CDN returns a 302 redirect back to our Atlassian site along the lines of:
https://mydomain.atlassian.net/secure/useravatar?size=small&ownerId=my.acct&avatarId=12345&noRedirect=true
The problem I'm running into is that the call to mydomain.atlassian.net needs to be authenticated, and I don't know how to do that via the API, without using cookies, which the API documentation recommends we avoid. So... what am I missing here?
Hi, here's what I got to work for our cloud account
Here is some TypeScript that demonstrates a class that handles the authentication and redirect required to get Avatar URLs...
import * as request from "request-promise-native";export interface IAtlassianSiteProxy { retrieveImage(url: string): Promise<IAtlassianAvatar>;}export interface IAtlassianAvatar { readonly data: Buffer; readonly contentType: string;}export class AtlassianSiteProxy implements IAtlassianSiteProxy { private _atlassianDomain: string; private _userName: string; private _password: string; private _apiUserName: string; private _apiKey: string; private _cookie: string = ''; public constructor(atlassianDomain: string, userName: string, password: string, apiUserName: string, apiKey: string) { this._atlassianDomain = atlassianDomain; this._userName = userName; this._password = password; this._apiUserName = apiUserName; this._apiKey = apiKey; } /** * Launch session to get cookie value */ private async getAtlassianCookie(): Promise<string> { if (this._cookie) { return this._cookie; } var options = { uri: this._atlassianDomain + '/rest/auth/1/session', method: 'POST', headers: { "Accept": "application/json", "Content-type": "application/json" }, auth: { 'user': this._apiUserName, 'pass': this._apiKey }, body: { username: this._userName, password: this._password }, json: true, resolveWithFullResponse: true, followRedirect: true, followAllRedirects: true }; let response = await request(options); let headers = response.headers; /* Flatten out cookies into a single string */ if (headers['set-cookie']) { this._cookie = headers['set-cookie'].map(function (cookie: string) { let i = cookie.indexOf(';'); let j = cookie.indexOf('='); if (i > j && i > -1) { let name = cookie.substr(0, j); let value = cookie.substr(j + 1, i - j - 1); return name + '=' + value; } else { return ''; } }).join('; ').toString(); return this._cookie; } throw "Cookies not received from Atlassian session"; } /** * Retrieve the image specified by the URL, handling authentication and redirects * @param url */ public async retrieveImage(url: string): Promise<IAtlassianAvatar> { let cookie = await this.getAtlassianCookie(); let avatarOptions = { method: 'GET', uri: url, headers: { Connection: 'keep-alive', Cookie: cookie }, auth: { 'user': this._userName, 'pass': this._apiKey }, encoding: null, resolveWithFullResponse: true, followRedirect: true }; let response = await request(avatarOptions); let contentType = response.headers['content-type']; let data = response.body; return { contentType: contentType, data: data }; }}
Dear @Jason Terando,
you have to do basic authentication (normally) and add a custom header (Content-Type: application/json), first. Then
GET /api/2/issue/<issue key>
should work.
For some API functions, it only works when adding additional headers:
accept: application/json
X-Atlassian-Token: nocheck
So long
Thomas
Hi @Thomas Deiler, I tried adding your suggested headers, to no avail. I suspect the problem is that the second URL, to get the avatar file, is not an API call, but a site call. Somehow, I have to get the cookies required to access the site, not just the API.
I reproduced your problems in my environment - I'll come back when I solved it.
Thank you very much!
Dear @Jason Terando
Ok - got it. My solution is with wget, but this can be for sure adapted to any other program (like curl) or programming language.
I have looked at the source code of the login page of Jira. Username and password are stored in variables os_username and os_password. Additionally the 'save login on my computer' has to be checked. This is the variable os_cookie.
wget -d --save-cookies cookies.txt --keep-session-cookie --post-data 'os_username=admin&os_password=admin&os_cookie=true' http://localhost:8080/login.jsp -O login-result.html
This will authorize you, session saved to cookie.
wget -d --load-cookies cookies.txt http://localhost:8080/secure/useravatar?size=medium&avatarId=10122 -O avatar.png
This will download one avatar, taking the session from before. The '-d' option delivers more output, to see the HTTP header information.
Tell me, if you could reproduce what I found out.
Hi, first - thanks again for taking the time to look into this. I ran wget on my machine and ended up getting the "generic" icon.
The cookie file from wget looks like this:
````
.atlassian.com TRUE / TRUE 0 cloud.session.token deletedid.atlassian.com FALSE / FALSE 0 atlassian.account.ffs.id (UUID).id.atlassian.com TRUE / TRUE 0 cloud.session.token deletedid.atlassian.com FALSE / TRUE 0 atlassian.account.xsrf.token (HexOrBinStringLookingValue)
When I browse to the secure/useravatar in Jira (and we're using the hosted version, probably should have said that explicitly) and look at the cookies going over, there are a lot more cookies getting sent:
_utma, _utmz, ajx_user_id, ajs_group_id, ajs_anonymous_id, atlassian.xsrf.token, _utmb, &tmc, &tmt, cloud.session.token, _csrf
The interesting one to me is cloud.session.token, where wget was setting that as "deleted", whereas when hitting the Atlassian site in the browser it is a big long value.
I guess the next thing I'll try is injecting the cookeis in manually until I figure out which one/s are really required...
It looks like you're new here. Sign in or register to get started.