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...
that sounds fine. Was my answer fine enough to be accepted?
Many thanks in advance
It looks like you're new here. Sign in or register to get started.