Skip to content

Commit

Permalink
mix-up attack protection
Browse files Browse the repository at this point in the history
  • Loading branch information
feyruzb committed Nov 25, 2024
1 parent 161106c commit 3f774da
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 54 deletions.
12 changes: 9 additions & 3 deletions docs/web/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,15 @@ CodeChecker also supports OAUTH-based authentication. The `authentication.method

This link in used for redirecting user for provider's authentication page

* `oauth_redirect_uri`
* `oauth_callback_url`

User will be redirected back to the provided link after login with returned data.
It should be constructed in that format `http://codechecker_path/login/OAuthLogin/provider` wher `provider` is the the name of the provider of OAuth and should match existing `provider_name`. The `oauth_callback_url` should also match the callback url specified in the config of your provider on their webpage.

Example of correct link using github, google and microsoft
* http://localhost:8080/login/OAuthLogin/github
* http://localhost:8080/login/OAuthLogin/google
* http://localhost:8080/login/OAuthLogin/microsoft

* `oauth_token_uri`

Expand Down Expand Up @@ -395,7 +401,7 @@ CodeChecker also supports OAUTH-based authentication. The `authentication.method
"oauth_client_id": "client id",
"oauth_client_secret": "client secret",
"oauth_authorization_uri": "https://accounts.google.com/o/oauth2/auth",
"oauth_redirect_uri": "http://localhost:8080/login",
"oauth_callback_url": "http://localhost:8080/login/provider",
"oauth_token_uri": "https://accounts.google.com/o/oauth2/token",
"oauth_user_info_uri": "https://www.googleapis.com/oauth2/v1/userinfo",
"oauth_scope": "openid email profile",
Expand All @@ -416,7 +422,7 @@ CodeChecker also supports OAUTH-based authentication. The `authentication.method

#### Oauth Details per each provider <a name ="oauth-details-per-each-provider"></a>

* Important: 'oauth_redirect_uri' must always match with link specified in the
* Important: 'oauth_callback_url' must always match with link specified in the
Providers settings when issuing an access token.

# Client-side configuration <a name="client-side-configuration"></a>
Expand Down
8 changes: 4 additions & 4 deletions web/server/codechecker_server/api/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def createLink(self, provider):
client_secret = oauth_config["oauth_client_secret"]
scope = oauth_config["oauth_scope"]
authorization_uri = oauth_config["oauth_authorization_uri"]
redirect_uri = oauth_config["oauth_redirect_uri"]
callback_url = oauth_config["oauth_callback_url"]
# code verifier for PKCE
pkce_verifier = generate_token(48)

Expand All @@ -232,7 +232,7 @@ def createLink(self, provider):
client_id,
client_secret,
scope=scope,
redirect_uri=redirect_uri,
redirect_uri=callback_url,
code_challenge_method='S256'
)

Expand Down Expand Up @@ -327,7 +327,7 @@ def performLogin(self, auth_method, auth_string):
scope = oauth_config["oauth_scope"]
token_url = oauth_config["oauth_token_uri"]
user_info_url = oauth_config["oauth_user_info_uri"]
redirect_uri = oauth_config["oauth_redirect_uri"]
callback_url = oauth_config["oauth_callback_url"]
allowed_users = oauth_config.get("allowed_users", [])
LOG.info("OAuth configuration loaded for provider: %s", provider)
session = None
Expand All @@ -336,7 +336,7 @@ def performLogin(self, auth_method, auth_string):
client_id,
client_secret,
scope=scope,
redirect_uri=redirect_uri,
redirect_uri=callback_url,
code_challenge_method='S256'
)

Expand Down
6 changes: 3 additions & 3 deletions web/server/config/server_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"oauth_client_id" : "ExampleClientID",
"oauth_client_secret": "ExampleClientSecret",
"oauth_authorization_uri": "https://github.com/login/oauth/authorize",
"oauth_redirect_uri": "http://path_To_CodeChecker_Login_Page",
"oauth_callback_url": "http://path_To_CodeChecker_Login_Page/provider",
"oauth_token_uri": "https://github.com/login/oauth/access_token",
"oauth_user_info_uri": "https://api.github.com/user",
"oauth_scope": "openid email profile",
Expand All @@ -83,7 +83,7 @@
"oauth_client_id" : "ExampleClientID",
"oauth_client_secret" : "ExampleClientSecret",
"oauth_authorization_uri" : "https://accounts.google.com/o/oauth2/auth",
"oauth_redirect_uri" : "http://path_To_CodeChecker_Login_Page",
"oauth_callback_url" : "http://path_To_CodeChecker_Login_Page/provider",
"oauth_token_uri" : "https://accounts.google.com/o/oauth2/token",
"oauth_user_info_uri" : "https://www.googleapis.com/oauth2/v1/userinfo",
"oauth_scope" : "openid email profile",
Expand All @@ -101,7 +101,7 @@
"oauth_client_id": "ExampleClientID",
"oauth_client_secret": "ExampleClientSecret",
"oauth_authorization_uri": "https://login.microsoftonline.com/92e84ceb-fbfd-47ab-be52-080c6b87953f/oauth2/v2.0/authorize",
"oauth_redirect_uri": "http://path_To_CodeChecker_Login_Page",
"oauth_callback_url": "http://path_To_CodeChecker_Login_Page/provider",
"oauth_token_uri": "https://login.microsoftonline.com/92e84ceb-fbfd-47ab-be52-080c6b87953f/oauth2/v2.0/token",
"oauth_user_info_uri": "https://graph.microsoft.com/v1.0/me",
"oauth_scope": "User.Read email profile openid",
Expand Down
5 changes: 5 additions & 0 deletions web/server/vue-cli/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export default new Router({
alias: [ "/login.html" ],
component: () => import("@/views/Login")
},
{
path: "/login/oAuthlogin/:provider",
name: "oauthlogin",
component: () => import("@/views/OAuthLogin")
},
{
path: "/userguide",
name: "userguide",
Expand Down
41 changes: 0 additions & 41 deletions web/server/vue-cli/src/views/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
Login with {{ provider }}
</v-btn>
</v-card-text>
{{ url }}
</v-card>
</v-dialog>
</v-container>
Expand Down Expand Up @@ -171,7 +170,6 @@ export default {
mounted() {
this.fixAutocomplete();
this.getProviders();
this.detectCallback();
},
methods: {
Expand All @@ -195,45 +193,6 @@ export default {
this.error = true;
});
},
detectCallback() {
const url = this.$route.query;
const provider = localStorage.getItem("oauth_provider");
const state = localStorage.getItem("oauth_state");
const code_challenge = localStorage.getItem("code_challenge");
const method = localStorage.getItem("method");
if (url.code != null && url.state != null) {
if (url.state != state) {
this.errorMsg = "Invalid state!";
this.error = true;
return;
}
const oauth_data_id = localStorage.getItem("oauth_data_id");
const baseUrl = window.location.href.replace("#", "");
const baseUrlOAuthId = `${baseUrl}&oauth_data_id=${oauth_data_id}`;
const baseMethod = `${baseUrlOAuthId}&code_challenge_method=${method}`;
const fullUrl = `${baseMethod}&code_challenge=${code_challenge}`;
this.$store
.dispatch(LOGIN, {
type: "oauth",
provider: provider,
url: fullUrl
})
.then(() => {
this.success = true;
this.error = false;
const w = window.location;
window.location.href = w.origin + w.pathname;
}).catch(err => {
this.errorMsg = `Failed to log in! ${err.message}`;
this.error = true;
this.$router.replace({ name: "login" });
});
}
},
getProviders() {
new Promise(resolve => {
authService.getClient().getOauthProviders(
Expand Down
124 changes: 124 additions & 0 deletions web/server/vue-cli/src/views/OAuthLogin.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<template>
<v-container>
<v-row>
<v-col cols="12">
<v-card>
<v-card-text class="px-0 pb-0">
<alerts
:success="success"
success-msg="Successfully logged in!"
:error="error"
:error-msg="errorMsg"
/>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>

<script>
import { mapGetters } from "vuex";
import { LOGIN } from "@/store/actions.type";
import Alerts from "@/components/Alerts.vue";
export default {
name: "OAuthLogin",
components: {
alerts: Alerts
},
data() {
return {
success: false,
error: false,
errorMsg: null,
};
},
computed: {
...mapGetters([
"isAuthenticated"
])
},
created() {
if (this.isAuthenticated) {
this.$router.replace({ name: "products" });
}
},
mounted() {
this.detectCallback();
},
methods: {
detectCallback() {
const url = this.$route.query;
const provider = this.$route.params.provider;
const state = localStorage.getItem("oauth_state");
const code_challenge = localStorage.getItem("code_challenge");
const method = localStorage.getItem("method");
if (url.code != null && url.state != null) {
if (url.state != state) {
this.errorMsg = "Invalid state!";
this.error = true;
this.callback = true;
return;
}
const oauth_data_id = localStorage.getItem("oauth_data_id");
const baseUrl = window.location.href.replace("#", "");
const baseUrlOAuthId = `${baseUrl}&oauth_data_id=${oauth_data_id}`;
const baseMethod = `${baseUrlOAuthId}&code_challenge_method=${method}`;
const fullUrl = `${baseMethod}&code_challenge=${code_challenge}`;
this.$store
.dispatch(LOGIN, {
type: "oauth",
provider: provider,
url: fullUrl
})
.then(() => {
this.success = true;
this.error = false;
const w = window.location;
window.location.href = w.origin + w.pathname;
}).catch(err => {
this.errorMsg = `Failed to log in! ${err.message}`;
this.error = true;
this.$router.replace({ name: "login" });
});
}
}
}
};
</script>

<style lang="scss" scoped>
#btn-container > button {
margin: 0 !important;
margin-top: 10px !important;
}
#avatar {
position: absolute;
margin: 0 auto;
left: 0;
right: 0;
top: -70px;
width: 95px;
height: 95px;
border-radius: 50%;
z-index: 9;
padding: 15px;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.1);
}
#login-btn {
font-size: 1.2em;
}
</style>
6 changes: 3 additions & 3 deletions web/tests/libtest/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ def enable_auth(workspace):
"oauth_client_id": "1",
"oauth_client_secret": "1",
"oauth_authorization_uri": "http://localhost:3000/login",
"oauth_redirect_uri": "http://localhost:3000/login",
"oauth_callback_url": "http://localhost:8080/login/OAuthLogin/github",
"oauth_token_uri": "http://localhost:3000/token",
"oauth_user_info_uri": "http://localhost:3000/get_user",
"oauth_scope": "openid email profile",
Expand All @@ -382,7 +382,7 @@ def enable_auth(workspace):
"oauth_client_id": "2",
"oauth_client_secret": "2",
"oauth_authorization_uri": "http://localhost:3000/login",
"oauth_redirect_uri": "http://localhost:3000/login",
"oauth_callback_url": "http://localhost:8080/login/OAuthLogin/google",
"oauth_token_uri": "http://localhost:3000/token",
"oauth_user_info_uri": "http://localhost:3000/get_user",
"oauth_scope": "openid email profile",
Expand All @@ -398,7 +398,7 @@ def enable_auth(workspace):
"oauth_client_id": "3",
"oauth_client_secret": "3",
"oauth_authorization_uri": "http://localhost:3000/login",
"oauth_redirect_uri": "http://localhost:3000/login",
"oauth_callback_url": "http://localhost:8080/login/OAuthLogin/dummy",
"oauth_token_uri": "http://localhost:3000/token",
"oauth_user_info_uri": "http://localhost:3000/get_user",
"oauth_scope": "openid email profile",
Expand Down

0 comments on commit 3f774da

Please sign in to comment.