I am building a Jira add-on that gives provides the user with the status of an object within my own API (not within Jira). My API is protected using OAuth 2.0. What is the best way to authenticate to my API from my Jira add-on?
I like how the Jira + GitHub/Bitbucket integration works. Specifically, the user retrieves API keys from GitHub and puts them in Jira. Jira then uses these keys to authenticate with and then retrieve data from GitHub. At least, this is how I think it works.
How can I achieve this same effect for my Jira add-on?
When you are building a cloud add-on then you can handle authentication without bothering admins (they don't need to copy anything).
To integrate yourself with Jira UI you need to create a webpanel or page, in both cases, Jira will ask your site to render the HTML code and the request will include JWT token. Inside you will have information about which user did the request.
Now, you can authenticate Jira users to your API in several ways:
render a time-limited token to the HTML and use it to authenticate calls to your API. As a downside of this solution, if someone will keep the page open without reloading for long enough (longer than your time limit) the token will become invalid.
provide a resource to retrieve time-limited token (validate JWT signature provided by Jira to be sure request really comes from particular Jira instance) and retrieve the token every time before doing the request (or every N minutes depending on your time limit).
or if you really want to bother admins then create a configuration page and let them save API keys by hand (I assume they will have to retrieve those keys from you somehow, this additional step may discourage many admins), in this configuration page you will include JS code that on submit will save API keys as Application property and later you will have to retrieve this before making requests to your API. With this approach however, admins will not be able to restrict access to your API to a subset of users with Jira permissions (every logged in user can access application properties, in open instances even anonymous users).
If you are unsure how to validate JWT Token you can read this developer guide. Also, you can make your life easier by using one of the provided framework and tools, for example, atlassian-connect-spring-boot will take care of installation handshake, JWT authentication and authentication to Jira REST API from your server.
Related
I have a CLI tool that requires search access, on behalf of the user. I've set up an application on our team's workspace with all of the right scopes and configuration.
However, I am dismayed at how oppressive the OAuth access token process is for CLI tools. Step 1 in their process is to provide a link to a custom web site that has an "Add to Slack" button. This already extends a simple CLI tool into requiring an entire web site, but the button is merely a static URL with parameters about the app and scopes. So far, a static page from Confluence, GitHub, or some other wiki-based project space would be enough.
Step 2 is where the user grants access to the application through their browser. However, Step 3 is where the action redirects to a special, dynamic page that requires access to take a special code, and translate it into an actual usable token for the user to plug into the CLI configuration. This extra step requires a special web page that Slack does not provide to do the translation, instead of just handing a token directly to the user.
Even worse, the API call requires secret client_id and client_secret parameters that would be plain as day in an shared or open-source CLI tool. (Despite the API documentation saying otherwise, both of these parameters are actually required.)
For example, Slackcat requires a one-page special web site expressly for the purposes of fielding OAuth requests. This is a web page that cannot be opened to the public because it would reveal the secret parameters. Unfortunately, Slackcat does not have the right scope levels I need, so I can't just borrow its web site for token generation.
Is there a better way to sidestep this process and allow a simple CLI tool to just get the right user access token it needs?
OAuth2 is fundamentally built around web browsers. The entire point is to allow the user's web browser to be redirected to the OAuth2 provider's website for password entry, so that the user's credentials are never visible to you or pass through any infrastructure you control.
This necessarily involves spawning a browser and sending it to a site you control to begin the OAuth2 flow by setting up state and redirecting the user to the OAuth2 provider, and then complete the OAuth2 flow by handling the redirect back from the OAuth2 provider and performing the code/token exchange. You can't do any of this with a static site, you need a web service.
Is there a better way to sidestep this process and allow a simple CLI tool to just get the right user access token it needs?
No. If there were, it would be a vulnerability in OAuth2 that should be fixed, not exploited to bypass the entire point of OAuth2.
I have a website that exposes a public API. I want to secure this public API using OAuth 2. In order to minimize the number of code paths to maintain, I want to refactor my website to use the OAuth 2-secured public API endpoints.
The way I intend to do this is to register an OAuth 2 Client in my server as "my website", and then have that fetch a short-lived token. I see 2 problems with this approach:
My client would have to effectively have every scope, since the
website encompasses every possible action. The API is just a subset
of this (though I'm hoping to change that). The second issue is
security and caching of the token. The token would live for an hour.
If the user refreshes the page, do I fetch another token? If I store
it locally in a cookie or localStorage, is there a security
vulnerable of some sort?
Let's say I register a different OAuth Client for each page of my UI. The would make it so that the token in #2 would have limited scope if stolen, but it gets extremely tedious.
The alternative is to not use the public API on my website, and protection relies on CORS. Malicious attackers cannot access these endpoints because they are only allowed to come from the domain the user is on (and things like nonces).
Sounds like you want towards a model based on a Browser UI calling APIs directly, which is certainly the most attractive architecturally.
This may be the first step to a Single Page App architecture, which tends to provide the simplest and cleanest solution.
See Open Id Connect for browser apps for latest standards.
In an SPA the UI is cookieless and it is common to store short lived access tokens in HTML5 session storage, which means the user can refresh the page ok
It is true that all scopes are retrieved after login, but if you keep scopes simple and authorize in your API based on user rights you can mitigate that
The above token storage is the default behaviour for the certified OIDC Client Library and widely used.
There is a cross site scripting risk, that malicious content in your browser tab can get a token and call the API - but you should be protecting against this anyway.
Older solutions such as use of auth cookies tend to have their own (and bigger) risks such as cross site request forgery, where any malicious content in any browser tab can send the cookie to your API.
Evaluating whether to use HTML5 storage of tokens is about more than just the technical mechanism - it is about acceptable trade offs around usability and what can be done with the token. My blog post on UI token storage drills into this.
If it helps, my blog also has quite a few posts and code samples on SPAs, in case it is of interest.
There used to be a way for an anonymous user - such as a script - to query certain aspects of Jenkins via its REST API. For example, finding out the name of a user who started a particular build job, or the date it executed. However the security model changed in the last few years which seems to make this much more difficult, even for read-only access.
I'm using Jenkins with ADS authentication. I need to provide API access to a script, but I don't want to use a particular user's personal API token (hard-coded in the script) because the script might be run by anyone in my organisation, including as part of other automation, and I don't want to tie this to a specific employee.
Instead I need a job-based token - one which is set for the job. There's a build token, but I don't think this works for the REST API.
I thought about creating a special "auto" user, and creating a token for that user, but the Active Directory config seems to prevent me from creating new Jenkins users. I cannot create a new AD user because I simply don't have the ability to do that in my organisation.
What's the best approach to using API tokens for anonymous access? Also, is there a way to ensure the token only provides limited access - e.g. read only? Ideally such a token would be restricted to a specific set of jobs, rather than global.
There is not. Feature request is JENKINS-56465.
See https://stackoverflow.com/a/49938577/97831 on how to add users to the Jenkins database with authentication already enabled.
API tokens are the same as password, functionally speaking. If you could do it with the password, you can do it with the API token. If you want an API token to have read-only access, then the user it's associated with should be restricted to read-only access.
I'm curious what is the "best practice" for authenticating against a restful-api that is protected by Google IAP.
Allow me to break it down step by step to elucidate what I am trying to achieve:
Go to my dev environment's url: dev.blah.com. Here, I am prompted by IAP to log-in. I log in. I now have access to my SPA.
I am browsing my SPA. But! I'm unable to talk to my API, because it is ALSO protected by IAP.
I've read that I can do programmatic authentication in the documentation but I'm unsure if my particular use case is suited for programmatic authentication, or if it will even be SECURE.
So, am I correct in that I will have to implement a client-side programmatic-authentication workflow in order to access my API?
Or is there an alternative way to say "Once I'm authenticated to access THIS IAP-protected resource, i can log into these other resources as well." I cannot simply copy the token because it is http-only and the cookie is restricted to my current domain.
Some additional information:
My services are running in a Google Kubernetes Engine cluster and have automatically created load balancers based off of ingress objects I declare.
Each IAP-protected environment gets it's own OAuth credentials, and I configure the load-balancers to use IAP using: gcloud compute backend-services update [backend-service] --global --iap=enabled,oauth2-client-id=[the_id],oauth2-client-secret=[the_secret]
let me make sure I understand what you're trying to do. It sounds like you want to call your API from JavaScript inside the web browser, is that correct?
If so, and:
All backend services are configured to use the same OAuth client ID.
The API and the SPA are serving off the same domain.
then I think things will just work, because the JavaScript-generated HTTP requests will be sent with the IAP session cookie. ... Which must not be your setup, or things would just be working which clearly they aren't. :>
If you're not able to arrange for your API calls to use the IAP session cookie generated when you authenticate to the SPA, this will be tricky. You wouldn't want to use service account authentication from the browser, since that would give all end-users access to the service account.
Hm, it looks like there is a way to do Google OAuth from JavaScript: https://developers.google.com/api-client-library/javascript/features/authentication -- I haven't tried it, but if you're able to get that working, you ought to be able to use a flow like https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_desktop_app . If you want to go that route, let me know how it goes and I'd love to help you get unstuck and then get that approach added to our documentation!
--Matthew, Google Cloud IAP engineering
Apologies for the oddly worded title, however I could not come up with a better one.
My application should be able to perform a limited set of actions on an Enterprise Google Apps system. Users submit requests to the application, the application interprets these requests and then makes requests to Google resources as necessary.The point is that users, who normally do not have permissions to access/modify the google apps resources, will be able to use this application to do so in the limited ways that it allows.
My problem lies in the apparent fact that the OAuth2.0 authorization flow seems designed to allow third party client applications to authorize themselves as the user and access/modify the user's google resources, rather than a global administrator's. In other words, a normal API key type deal. Unfortunately it seems that Google's AdminSDK will only work with OAuth2 authorization.
Is there a way to use Google's AdminSDK API with OAuth2 (permanent access token, maybe? API key?) to do what I want? Or is there a different API I should be trying? The now-deprecated Provisioning API seemed to be able to do this.
I feel like there should be a way for the application to just pull something out of a secrets.json or secrets.yml, include that in the API authorization request and have Google servers recognize and grant access to the application without the user ever needing to see what's going on.
For the record I'm using Ruby on Rails, though I don't think that affects the question very much.