{"action":"created","comment":{"url":"https://api.github.com/repos/mattermost/platform/pulls/comments/39289550","id":39289550,"diff_hunk":"@@ -33,22 +35,37 @@ type Result struct {\n }\n \n type Client struct {\n-\tUrl        string       // The location of the server like \"http://localhost/api/v1\"\n+\tUrl        string       // The location of the server like \"http://localhost:8065\"\n+\tApiUrl     string       // The api location of the server like \"http://localhost:8065/api/v1\"\n \tHttpClient *http.Client // The http client\n \tAuthToken  string\n+\tAuthType   string\n }\n \n // NewClient constructs a new client with convienence methods for talking to\n // the server.\n-func NewClient(url string) *Client {\n-\treturn &Client{url, &http.Client{}, \"\"}\n+func NewClient(url, apiUrl string) *Client {","path":"model/client.go","position":25,"original_position":25,"commit_id":"8e86ea8bfbbb6d289bc8ec484f2fd15c72937a62","original_commit_id":"8e86ea8bfbbb6d289bc8ec484f2fd15c72937a62","user":{"login":"coreyhulen","id":1431746,"avatar_url":"https://avatars.githubusercontent.com/u/1431746?v=3","gravatar_id":"","url":"https://api.github.com/users/coreyhulen","html_url":"https://github.com/coreyhulen","followers_url":"https://api.github.com/users/coreyhulen/followers","following_url":"https://api.github.com/users/coreyhulen/following{/other_user}","gists_url":"https://api.github.com/users/coreyhulen/gists{/gist_id}","starred_url":"https://api.github.com/users/coreyhulen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreyhulen/subscriptions","organizations_url":"https://api.github.com/users/coreyhulen/orgs","repos_url":"https://api.github.com/users/coreyhulen/repos","events_url":"https://api.github.com/users/coreyhulen/events{/privacy}","received_events_url":"https://api.github.com/users/coreyhulen/received_events","type":"User","site_admin":false},"body":"we should figure out a better way todo this.   client.go will be our driver library that we distribute.  having 2 urls is confusing.","created_at":"2015-09-11T16:34:02Z","updated_at":"2015-09-11T16:34:02Z","html_url":"https://github.com/mattermost/platform/pull/644#discussion_r39289550","pull_request_url":"https://api.github.com/repos/mattermost/platform/pulls/644","_links":{"self":{"href":"https://api.github.com/repos/mattermost/platform/pulls/comments/39289550"},"html":{"href":"https://github.com/mattermost/platform/pull/644#discussion_r39289550"},"pull_request":{"href":"https://api.github.com/repos/mattermost/platform/pulls/644"}}},"pull_request":{"url":"https://api.github.com/repos/mattermost/platform/pulls/644","id":44683221,"html_url":"https://github.com/mattermost/platform/pull/644","diff_url":"https://github.com/mattermost/platform/pull/644.diff","patch_url":"https://github.com/mattermost/platform/pull/644.patch","issue_url":"https://api.github.com/repos/mattermost/platform/issues/644","number":644,"state":"open","locked":false,"title":"MM-1419 Implement OAuth2 service provider functionality.","user":{"login":"jwilander","id":2672098,"avatar_url":"https://avatars.githubusercontent.com/u/2672098?v=3","gravatar_id":"","url":"https://api.github.com/users/jwilander","html_url":"https://github.com/jwilander","followers_url":"https://api.github.com/users/jwilander/followers","following_url":"https://api.github.com/users/jwilander/following{/other_user}","gists_url":"https://api.github.com/users/jwilander/gists{/gist_id}","starred_url":"https://api.github.com/users/jwilander/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jwilander/subscriptions","organizations_url":"https://api.github.com/users/jwilander/orgs","repos_url":"https://api.github.com/users/jwilander/repos","events_url":"https://api.github.com/users/jwilander/events{/privacy}","received_events_url":"https://api.github.com/users/jwilander/received_events","type":"User","site_admin":false},"body":"This is a rather large pull request that implements a baseline for using Mattermost as an OAuth2 service provider. In this description I will give a brief overview of our OAuth2 flow, explain the basic architecture, and list what is missing and needs to be added in the future.\r\n\r\n**PLEASE DO NOT MERGE UNTIL MOST OF THE TEAM HAS HAD A CHANCE TO REVIEW AND HAS AGREED**\r\n\r\nThe OAuth2 spec can be found here: https://tools.ietf.org/html/rfc6749\r\n\r\n## The OAuth2 Flow (Authorization Code flow)\r\nNote: This is a BRIEF overview of the flow, a more detailed flow will be coming out in the future.\r\n\r\n1. A third-party logs in to their Mattermost acount and registers an application that wishes to access user data controlled by Mattermost. This is found under \"Account Settings\"->\"Developer\"->\"Applications\".\r\n2. The third-party is given a client id and client secret as the credentials for their newly registered application.\r\n3. The third-party performs a GET request to ```https://<mattermost_domain>/login/oauth2/authorize?response_type=code&client_id=CLIENTID&redirect_uri=REDIRECTURI&state=RANDOMSTRING```\r\n4. The user is now redirected to a Mattermost page, asking the user to allow or deny the third-party application access to their account.\r\n5. If the user clicks 'Allow', the browser will be redirect to the ```REDIRECTURI``` provided by the third-party in step 3 with the follow url query ```?code=AUTHCODE&state=RANDOMSTRING```\r\n6. The third-party must make sure ```state``` matches the one they provided in step 3\r\n7. The third-party will then make a POST request to exchange the ```code``` for an access token. The request will be made to ```https://<mattermost_domain>/api/v1/oauth2/access_token``` with the following body: \r\n\r\n    ```\r\n        client_id=CLIENT_ID&\r\n        client_secret=CLIENT_SECRET&\r\n        code=AUTHORIZATION_CODE&\r\n        grant_type=authorization_code&\r\n        redirect_uri=REDIRECT_URI\r\n    ```\r\n8. The server will respond with the following JSON body:\r\n\r\n    ```\r\n    {\r\n        \"access_token\": ACCESSTOKEN,\r\n        \"token_type\": \"bearer\",\r\n        \"expires_in\": 31536000, // expire time in seconds\r\n        \"scope\": \"\", // not implemented yet\r\n        \"refresh_token\": \"\", // not implemented yet\r\n    }\r\n    ```\r\n9. The third-party can now make API calls on behalf of the user by appending ```?access_token=ACCESSTOKEN``` to API urls.\r\n\r\n## Basic Architecture\r\n* Three new models were created to handle the new data we will need to store\r\n * OAuthApp Model: Tracks registered third-party applications\r\n * AuthData Model: Contains an OAuth2 authorization code and all the information pertaining to that code\r\n * AcccessData Model: Contains an OAuth2 access token and all the information pertaining to that token\r\n* A new API path called 'oauth' was created\r\n* The Session model was updated to refer to an access token\r\n* The context function ServeHTTP() was updated to create/store sessions for valid access tokens\r\n\r\n## Still To Do (possibly with this pr or with a future one)\r\n* Have @asaadmahmoodspin clean-up the new UI elements added\r\n* Implement the ability for users to revoke applications they have previously allowed (will need UI spec)\r\n* Implement the ability for app owners to edit their registered apps (will need UI spec)\r\n* Implement refresh tokens (and add expiry to access tokens)\r\n* Implement scope limiting\r\n* Create detailed docs explaining our OAuth2 flows, common errors, etc.\r\n","created_at":"2015-09-10T15:37:14Z","updated_at":"2015-09-11T16:34:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8a9cb7247c25101ad1f33e6afa19a76ce6ff59ed","assignee":{"login":"coreyhulen","id":1431746,"avatar_url":"https://avatars.githubusercontent.com/u/1431746?v=3","gravatar_id":"","url":"https://api.github.com/users/coreyhulen","html_url":"https://github.com/coreyhulen","followers_url":"https://api.github.com/users/coreyhulen/followers","following_url":"https://api.github.com/users/coreyhulen/following{/other_user}","gists_url":"https://api.github.com/users/coreyhulen/gists{/gist_id}","starred_url":"https://api.github.com/users/coreyhulen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreyhulen/subscriptions","organizations_url":"https://api.github.com/users/coreyhulen/orgs","repos_url":"https://api.github.com/users/coreyhulen/repos","events_url":"https://api.github.com/users/coreyhulen/events{/privacy}","received_events_url":"https://api.github.com/users/coreyhulen/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/mattermost/platform/milestones/3","html_url":"https://github.com/mattermost/platform/milestones/v0.8.0","labels_url":"https://api.github.com/repos/mattermost/platform/milestones/3/labels","id":1246518,"number":3,"title":"v0.8.0","description":"","creator":{"login":"it33","id":177788,"avatar_url":"https://avatars.githubusercontent.com/u/177788?v=3","gravatar_id":"","url":"https://api.github.com/users/it33","html_url":"https://github.com/it33","followers_url":"https://api.github.com/users/it33/followers","following_url":"https://api.github.com/users/it33/following{/other_user}","gists_url":"https://api.github.com/users/it33/gists{/gist_id}","starred_url":"https://api.github.com/users/it33/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/it33/subscriptions","organizations_url":"https://api.github.com/users/it33/orgs","repos_url":"https://api.github.com/users/it33/repos","events_url":"https://api.github.com/users/it33/events{/privacy}","received_events_url":"https://api.github.com/users/it33/received_events","type":"User","site_admin":false},"open_issues":4,"closed_issues":95,"state":"open","created_at":"2015-08-08T14:34:36Z","updated_at":"2015-09-11T15:47:45Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/mattermost/platform/pulls/644/commits","review_comments_url":"https://api.github.com/repos/mattermost/platform/pulls/644/comments","review_comment_url":"https://api.github.com/repos/mattermost/platform/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mattermost/platform/issues/644/comments","statuses_url":"https://api.github.com/repos/mattermost/platform/statuses/8e86ea8bfbbb6d289bc8ec484f2fd15c72937a62","head":{"label":"mattermost:mm-1419","ref":"mm-1419","sha":"8e86ea8bfbbb6d289bc8ec484f2fd15c72937a62","user":{"login":"mattermost","id":9828093,"avatar_url":"https://avatars.githubusercontent.com/u/9828093?v=3","gravatar_id":"","url":"https://api.github.com/users/mattermost","html_url":"https://github.com/mattermost","followers_url":"https://api.github.com/users/mattermost/followers","following_url":"https://api.github.com/users/mattermost/following{/other_user}","gists_url":"https://api.github.com/users/mattermost/gists{/gist_id}","starred_url":"https://api.github.com/users/mattermost/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattermost/subscriptions","organizations_url":"https://api.github.com/users/mattermost/orgs","repos_url":"https://api.github.com/users/mattermost/repos","events_url":"https://api.github.com/users/mattermost/events{/privacy}","received_events_url":"https://api.github.com/users/mattermost/received_events","type":"Organization","site_admin":false},"repo":{"id":37448451,"name":"platform","full_name":"mattermost/platform","owner":{"login":"mattermost","id":9828093,"avatar_url":"https://avatars.githubusercontent.com/u/9828093?v=3","gravatar_id":"","url":"https://api.github.com/users/mattermost","html_url":"https://github.com/mattermost","followers_url":"https://api.github.com/users/mattermost/followers","following_url":"https://api.github.com/users/mattermost/following{/other_user}","gists_url":"https://api.github.com/users/mattermost/gists{/gist_id}","starred_url":"https://api.github.com/users/mattermost/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattermost/subscriptions","organizations_url":"https://api.github.com/users/mattermost/orgs","repos_url":"https://api.github.com/users/mattermost/repos","events_url":"https://api.github.com/users/mattermost/events{/privacy}","received_events_url":"https://api.github.com/users/mattermost/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mattermost/platform","description":"Open source Slack-alternative in Golang and React","fork":false,"url":"https://api.github.com/repos/mattermost/platform","forks_url":"https://api.github.com/repos/mattermost/platform/forks","keys_url":"https://api.github.com/repos/mattermost/platform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mattermost/platform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mattermost/platform/teams","hooks_url":"https://api.github.com/repos/mattermost/platform/hooks","issue_events_url":"https://api.github.com/repos/mattermost/platform/issues/events{/number}","events_url":"https://api.github.com/repos/mattermost/platform/events","assignees_url":"https://api.github.com/repos/mattermost/platform/assignees{/user}","branches_url":"https://api.github.com/repos/mattermost/platform/branches{/branch}","tags_url":"https://api.github.com/repos/mattermost/platform/tags","blobs_url":"https://api.github.com/repos/mattermost/platform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mattermost/platform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mattermost/platform/git/refs{/sha}","trees_url":"https://api.github.com/repos/mattermost/platform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mattermost/platform/statuses/{sha}","languages_url":"https://api.github.com/repos/mattermost/platform/languages","stargazers_url":"https://api.github.com/repos/mattermost/platform/stargazers","contributors_url":"https://api.github.com/repos/mattermost/platform/contributors","subscribers_url":"https://api.github.com/repos/mattermost/platform/subscribers","subscription_url":"https://api.github.com/repos/mattermost/platform/subscription","commits_url":"https://api.github.com/repos/mattermost/platform/commits{/sha}","git_commits_url":"https://api.github.com/repos/mattermost/platform/git/commits{/sha}","comments_url":"https://api.github.com/repos/mattermost/platform/comments{/number}","issue_comment_url":"https://api.github.com/repos/mattermost/platform/issues/comments{/number}","contents_url":"https://api.github.com/repos/mattermost/platform/contents/{+path}","compare_url":"https://api.github.com/repos/mattermost/platform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mattermost/platform/merges","archive_url":"https://api.github.com/repos/mattermost/platform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mattermost/platform/downloads","issues_url":"https://api.github.com/repos/mattermost/platform/issues{/number}","pulls_url":"https://api.github.com/repos/mattermost/platform/pulls{/number}","milestones_url":"https://api.github.com/repos/mattermost/platform/milestones{/number}","notifications_url":"https://api.github.com/repos/mattermost/platform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mattermost/platform/labels{/name}","releases_url":"https://api.github.com/repos/mattermost/platform/releases{/id}","created_at":"2015-06-15T06:50:02Z","updated_at":"2015-09-11T12:30:06Z","pushed_at":"2015-09-11T16:11:47Z","git_url":"git://github.com/mattermost/platform.git","ssh_url":"git@github.com:mattermost/platform.git","clone_url":"https://github.com/mattermost/platform.git","svn_url":"https://github.com/mattermost/platform","homepage":"http://mattermost.org","size":15195,"stargazers_count":3005,"watchers_count":3005,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":253,"mirror_url":null,"open_issues_count":17,"forks":253,"open_issues":17,"watchers":3005,"default_branch":"master"}},"base":{"label":"mattermost:master","ref":"master","sha":"b440fd5f3c920b635d59bc5904f3d08d391ad79f","user":{"login":"mattermost","id":9828093,"avatar_url":"https://avatars.githubusercontent.com/u/9828093?v=3","gravatar_id":"","url":"https://api.github.com/users/mattermost","html_url":"https://github.com/mattermost","followers_url":"https://api.github.com/users/mattermost/followers","following_url":"https://api.github.com/users/mattermost/following{/other_user}","gists_url":"https://api.github.com/users/mattermost/gists{/gist_id}","starred_url":"https://api.github.com/users/mattermost/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattermost/subscriptions","organizations_url":"https://api.github.com/users/mattermost/orgs","repos_url":"https://api.github.com/users/mattermost/repos","events_url":"https://api.github.com/users/mattermost/events{/privacy}","received_events_url":"https://api.github.com/users/mattermost/received_events","type":"Organization","site_admin":false},"repo":{"id":37448451,"name":"platform","full_name":"mattermost/platform","owner":{"login":"mattermost","id":9828093,"avatar_url":"https://avatars.githubusercontent.com/u/9828093?v=3","gravatar_id":"","url":"https://api.github.com/users/mattermost","html_url":"https://github.com/mattermost","followers_url":"https://api.github.com/users/mattermost/followers","following_url":"https://api.github.com/users/mattermost/following{/other_user}","gists_url":"https://api.github.com/users/mattermost/gists{/gist_id}","starred_url":"https://api.github.com/users/mattermost/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattermost/subscriptions","organizations_url":"https://api.github.com/users/mattermost/orgs","repos_url":"https://api.github.com/users/mattermost/repos","events_url":"https://api.github.com/users/mattermost/events{/privacy}","received_events_url":"https://api.github.com/users/mattermost/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mattermost/platform","description":"Open source Slack-alternative in Golang and React","fork":false,"url":"https://api.github.com/repos/mattermost/platform","forks_url":"https://api.github.com/repos/mattermost/platform/forks","keys_url":"https://api.github.com/repos/mattermost/platform/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mattermost/platform/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mattermost/platform/teams","hooks_url":"https://api.github.com/repos/mattermost/platform/hooks","issue_events_url":"https://api.github.com/repos/mattermost/platform/issues/events{/number}","events_url":"https://api.github.com/repos/mattermost/platform/events","assignees_url":"https://api.github.com/repos/mattermost/platform/assignees{/user}","branches_url":"https://api.github.com/repos/mattermost/platform/branches{/branch}","tags_url":"https://api.github.com/repos/mattermost/platform/tags","blobs_url":"https://api.github.com/repos/mattermost/platform/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mattermost/platform/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mattermost/platform/git/refs{/sha}","trees_url":"https://api.github.com/repos/mattermost/platform/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mattermost/platform/statuses/{sha}","languages_url":"https://api.github.com/repos/mattermost/platform/languages","stargazers_url":"https://api.github.com/repos/mattermost/platform/stargazers","contributors_url":"https://api.github.com/repos/mattermost/platform/contributors","subscribers_url":"https://api.github.com/repos/mattermost/platform/subscribers","subscription_url":"https://api.github.com/repos/mattermost/platform/subscription","commits_url":"https://api.github.com/repos/mattermost/platform/commits{/sha}","git_commits_url":"https://api.github.com/repos/mattermost/platform/git/commits{/sha}","comments_url":"https://api.github.com/repos/mattermost/platform/comments{/number}","issue_comment_url":"https://api.github.com/repos/mattermost/platform/issues/comments{/number}","contents_url":"https://api.github.com/repos/mattermost/platform/contents/{+path}","compare_url":"https://api.github.com/repos/mattermost/platform/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mattermost/platform/merges","archive_url":"https://api.github.com/repos/mattermost/platform/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mattermost/platform/downloads","issues_url":"https://api.github.com/repos/mattermost/platform/issues{/number}","pulls_url":"https://api.github.com/repos/mattermost/platform/pulls{/number}","milestones_url":"https://api.github.com/repos/mattermost/platform/milestones{/number}","notifications_url":"https://api.github.com/repos/mattermost/platform/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mattermost/platform/labels{/name}","releases_url":"https://api.github.com/repos/mattermost/platform/releases{/id}","created_at":"2015-06-15T06:50:02Z","updated_at":"2015-09-11T12:30:06Z","pushed_at":"2015-09-11T16:11:47Z","git_url":"git://github.com/mattermost/platform.git","ssh_url":"git@github.com:mattermost/platform.git","clone_url":"https://github.com/mattermost/platform.git","svn_url":"https://github.com/mattermost/platform","homepage":"http://mattermost.org","size":15195,"stargazers_count":3005,"watchers_count":3005,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":253,"mirror_url":null,"open_issues_count":17,"forks":253,"open_issues":17,"watchers":3005,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mattermost/platform/pulls/644"},"html":{"href":"https://github.com/mattermost/platform/pull/644"},"issue":{"href":"https://api.github.com/repos/mattermost/platform/issues/644"},"comments":{"href":"https://api.github.com/repos/mattermost/platform/issues/644/comments"},"review_comments":{"href":"https://api.github.com/repos/mattermost/platform/pulls/644/comments"},"review_comment":{"href":"https://api.github.com/repos/mattermost/platform/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mattermost/platform/pulls/644/commits"},"statuses":{"href":"https://api.github.com/repos/mattermost/platform/statuses/8e86ea8bfbbb6d289bc8ec484f2fd15c72937a62"}}}}