How to build BitBucket Cloud add-on in Rails → lifecycle
31 May 2016Time to handle authentication between the service and BitBucket itself.
This article is Part 4 in a 7-Part Series.
- Part 1 - How to build BitBucket Cloud add-on in Rails → bootstraping rails
- Part 2 - How to build BitBucket Cloud add-on in Rails → add-on descriptor
- Part 3 - How to build BitBucket Cloud add-on in Rails → installation
- Part 4 - This Article
- Part 5 - How to build BitBucket Cloud add-on in Rails → user interface
- Part 6 - How to build BitBucket Cloud add-on in Rails → accessing BitBucket API from JavaScript
- Part 7 - How to build BitBucket Cloud add-on in Rails → accessing BitBucket API from the server
I'm not going to go into details about authentication as it is well described already.
Just a reminder - to authenticate requests made by the add-on I need to obtain JWT when it is installed by the user.
I need to add additional routes to config/routes.rb
:
post '/installed', to: 'lifecycle#installed'
post '/uninstalled', to: 'lifecycle#uninstalled'
Atlassian JWT authentication does the heavy lifting for me:
class LifecycleController < ApplicationController
include AtlassianJwtAuthentication::Filters
before_action :on_add_on_installed, only: [:installed]
before_action :on_add_on_uninstalled, only: [:uninstalled]
def installed
head(:no_content)
end
def uninstalled
head(:no_content)
end
end
Remove and install the add-on again and you will see that this time Rails will store the token for future use:
Started POST "/installed" for 104.192.143.193 at 2016-05-31 21:31:13 +0200
Processing by LifecycleController#installed as */*
Parameters: {"productType"=>"bitbucket", "principal"=>{"username"=>"pawelniewiadomski", "website"=>nil, "display_name"=>"Pawel Niewiadomski", "uuid"=>"{e503b860-9bee-4011-82d4-95a84c0f2743}", "links"=>{"self"=>{"href"=>"https://api.bitbucket.org/2.0/users/pawelniewiadomski"}, "html"=>{"href"=>"https://bitbucket.org/pawelniewiadomski/"}, "avatar"=>{"href"=>"https://bitbucket.org/account/pawelniewiadomski/avatar/32/"}}, "created_on"=>"2012-05-22T21:01:29.056667+00:00", "location"=>nil, "type"=>"user"}, "eventType"=>"installed", "baseUrl"=>"https://bitbucket.org", "publicKey"=>"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBFq+6Iq5J9AZzTZQfZEba9udHTIJToJnoDvWVHk8jKZIrMrVT1oJoAec84+nBhiO/8neqvbTlD7MeIb5aTDZo8YVhBKmQuEJ5RY56EakoR4x5oILsz/Ki5O4nGWSeTCCG1hj4heVsUi77umkYG5sZyHKNO+P+SwctTH1GEBDwswIDAQAB", "user"=>{"username"=>"pawelniewiadomski", "website"=>nil, "display_name"=>"Pawel Niewiadomski", "uuid"=>"{e503b860-9bee-4011-82d4-95a84c0f2743}", "links"=>{"self"=>{"href"=>"https://api.bitbucket.org/2.0/users/pawelniewiadomski"}, "html"=>{"href"=>"https://bitbucket.org/pawelniewiadomski/"}, "avatar"=>{"href"=>"https://bitbucket.org/account/pawelniewiadomski/avatar/32/"}}, "created_on"=>"2012-05-22T21:01:29.056667+00:00", "location"=>nil, "type"=>"user"}, "key"=>"stars.development", "baseApiUrl"=>"https://api.bitbucket.org", "clientKey"=>"connection:308533", "sharedSecret"=>"WOZ+mJsDKswFotc4yhdRyKoUdJc64KXbDG7Lm2BYCUw", "lifecycle"=>{"productType"=>"bitbucket", "principal"=>{"username"=>"pawelniewiadomski", "website"=>nil, "display_name"=>"Pawel Niewiadomski", "uuid"=>"{e503b860-9bee-4011-82d4-95a84c0f2743}", "links"=>{"self"=>{"href"=>"https://api.bitbucket.org/2.0/users/pawelniewiadomski"}, "html"=>{"href"=>"https://bitbucket.org/pawelniewiadomski/"}, "avatar"=>{"href"=>"https://bitbucket.org/account/pawelniewiadomski/avatar/32/"}}, "created_on"=>"2012-05-22T21:01:29.056667+00:00", "location"=>nil, "type"=>"user"}, "eventType"=>"installed", "baseUrl"=>"https://bitbucket.org", "publicKey"=>"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCBFq+6Iq5J9AZzTZQfZEba9udHTIJToJnoDvWVHk8jKZIrMrVT1oJoAec84+nBhiO/8neqvbTlD7MeIb5aTDZo8YVhBKmQuEJ5RY56EakoR4x5oILsz/Ki5O4nGWSeTCCG1hj4heVsUi77umkYG5sZyHKNO+P+SwctTH1GEBDwswIDAQAB", "user"=>{"username"=>"pawelniewiadomski", "website"=>nil, "display_name"=>"Pawel Niewiadomski", "uuid"=>"{e503b860-9bee-4011-82d4-95a84c0f2743}", "links"=>{"self"=>{"href"=>"https://api.bitbucket.org/2.0/users/pawelniewiadomski"}, "html"=>{"href"=>"https://bitbucket.org/pawelniewiadomski/"}, "avatar"=>{"href"=>"https://bitbucket.org/account/pawelniewiadomski/avatar/32/"}}, "created_on"=>"2012-05-22T21:01:29.056667+00:00", "location"=>nil, "type"=>"user"}, "key"=>"stars.development", "baseApiUrl"=>"https://api.bitbucket.org", "clientKey"=>"connection:308533", "sharedSecret"=>"WOZ+mJsDKswFotc4yhdRyKoUdJc64KXbDG7Lm2BYCUw"}}
JwtToken Load (25.9ms) SELECT "jwt_tokens".* FROM "jwt_tokens" WHERE "jwt_tokens"."client_key" = $1 AND "jwt_tokens"."addon_key" = $2 ORDER BY "jwt_tokens"."id" ASC LIMIT $3 [["client_key", "connection:308533"], ["addon_key", "stars.development"], ["LIMIT", 1]]
Unpermitted parameters: productType, principal, eventType, baseUrl, publicKey, user, key, baseApiUrl, sharedSecret, lifecycle
Unpermitted parameters: productType, principal, eventType, baseUrl, publicKey, user, baseApiUrl, clientKey, sharedSecret, lifecycle
(0.1ms) BEGIN
SQL (6.0ms) INSERT INTO "jwt_tokens" ("addon_key", "client_key", "shared_secret", "product_type") VALUES ($1, $2, $3, $4) RETURNING "id" [["addon_key", "stars.development"], ["client_key", "connection:308533"], ["shared_secret", "WOZ+mJsDKswFotc4yhdRyKoUdJc64KXbDG7Lm2BYCUw"], ["product_type", "atlassian:bitbucket"]]
(1.1ms) COMMIT
Completed 204 No Content in 92ms (ActiveRecord: 69.2ms)