You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

819 lines
22 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
10 years ago
10 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
10 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
10 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
7 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
Add single sign-on support via SSPI on Windows (#8463) * Add single sign-on support via SSPI on Windows * Ensure plugins implement interface * Ensure plugins implement interface * Move functions used only by the SSPI auth method to sspi_windows.go * Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected * Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links. * Update documentation for the new 'SPNEGO with SSPI' login source * Mention in documentation that ROOT_URL should contain the FQDN of the server * Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing) * Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources) * Add option in SSPIConfig for removing of domains from logon names * Update helper text for StripDomainNames option * Make sure handleSignIn() is called after a new user object is created by SSPI auth method * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Remove default value from text of form field helper Co-Authored-By: Lauris BH <lauris@nix.lv> * Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates * Remove code duplication * Log errors in ActiveLoginSources Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert suffix of randomly generated E-mails for Reverse proxy authentication Co-Authored-By: Lauris BH <lauris@nix.lv> * Revert unneeded white-space change in template Co-Authored-By: Lauris BH <lauris@nix.lv> * Add copyright comments at the top of new files * Use loopback name for randomly generated emails * Add locale tag for the SSPISeparatorReplacement field with proper casing * Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields * Update docs/content/doc/features/authentication.en-us.md Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Remove Priority() method and define the order in which SSO auth methods should be executed in one place * Log authenticated username only if it's not empty * Rephrase helper text for automatic creation of users * Return error if more than one active SSPI auth source is found * Change newUser() function to return error, letting caller log/handle the error * Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed * Refactor initialization of the list containing SSO auth methods * Validate SSPI settings on POST * Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page * Make 'Default language' in SSPI config empty, unless changed by admin * Show error if admin tries to add a second authentication source of type SSPI * Simplify declaration of global variable * Rebuild gitgraph.js on Linux * Make sure config values containing only whitespace are not accepted
4 years ago
Oauth2 consumer (#679) * initial stuff for oauth2 login, fails on: * login button on the signIn page to start the OAuth2 flow and a callback for each provider Only GitHub is implemented for now * show login button only when the OAuth2 consumer is configured (and activated) * create macaron group for oauth2 urls * prevent net/http in modules (other then oauth2) * use a new data sessions oauth2 folder for storing the oauth2 session data * add missing 2FA when this is enabled on the user * add password option for OAuth2 user , for use with git over http and login to the GUI * add tip for registering a GitHub OAuth application * at startup of Gitea register all configured providers and also on adding/deleting of new providers * custom handling of errors in oauth2 request init + show better tip * add ExternalLoginUser model and migration script to add it to database * link a external account to an existing account (still need to handle wrong login and signup) and remove if user is removed * remove the linked external account from the user his settings * if user is unknown we allow him to register a new account or link it to some existing account * sign up with button on signin page (als change OAuth2Provider structure so we can store basic stuff about providers) * from gorilla/sessions docs: "Important Note: If you aren't using gorilla/mux, you need to wrap your handlers with context.ClearHandler as or else you will leak memory!" (we're using gorilla/sessions for storing oauth2 sessions) * use updated goth lib that now supports getting the OAuth2 user if the AccessToken is still valid instead of re-authenticating (prevent flooding the OAuth2 provider)
7 years ago
7 years ago
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package models
  6. import (
  7. "crypto/tls"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "net/smtp"
  12. "net/textproto"
  13. "strings"
  14. "code.gitea.io/gitea/modules/auth/ldap"
  15. "code.gitea.io/gitea/modules/auth/oauth2"
  16. "code.gitea.io/gitea/modules/auth/pam"
  17. "code.gitea.io/gitea/modules/log"
  18. "code.gitea.io/gitea/modules/setting"
  19. "code.gitea.io/gitea/modules/timeutil"
  20. "github.com/unknwon/com"
  21. "xorm.io/xorm"
  22. "xorm.io/xorm/convert"
  23. )
  24. // LoginType represents an login type.
  25. type LoginType int
  26. // Note: new type must append to the end of list to maintain compatibility.
  27. const (
  28. LoginNoType LoginType = iota
  29. LoginPlain // 1
  30. LoginLDAP // 2
  31. LoginSMTP // 3
  32. LoginPAM // 4
  33. LoginDLDAP // 5
  34. LoginOAuth2 // 6
  35. LoginSSPI // 7
  36. )
  37. // LoginNames contains the name of LoginType values.
  38. var LoginNames = map[LoginType]string{
  39. LoginLDAP: "LDAP (via BindDN)",
  40. LoginDLDAP: "LDAP (simple auth)", // Via direct bind
  41. LoginSMTP: "SMTP",
  42. LoginPAM: "PAM",
  43. LoginOAuth2: "OAuth2",
  44. LoginSSPI: "SPNEGO with SSPI",
  45. }
  46. // SecurityProtocolNames contains the name of SecurityProtocol values.
  47. var SecurityProtocolNames = map[ldap.SecurityProtocol]string{
  48. ldap.SecurityProtocolUnencrypted: "Unencrypted",
  49. ldap.SecurityProtocolLDAPS: "LDAPS",
  50. ldap.SecurityProtocolStartTLS: "StartTLS",
  51. }
  52. // Ensure structs implemented interface.
  53. var (
  54. _ convert.Conversion = &LDAPConfig{}
  55. _ convert.Conversion = &SMTPConfig{}
  56. _ convert.Conversion = &PAMConfig{}
  57. _ convert.Conversion = &OAuth2Config{}
  58. _ convert.Conversion = &SSPIConfig{}
  59. )
  60. // LDAPConfig holds configuration for LDAP login source.
  61. type LDAPConfig struct {
  62. *ldap.Source
  63. }
  64. // FromDB fills up a LDAPConfig from serialized format.
  65. func (cfg *LDAPConfig) FromDB(bs []byte) error {
  66. return json.Unmarshal(bs, &cfg)
  67. }
  68. // ToDB exports a LDAPConfig to a serialized format.
  69. func (cfg *LDAPConfig) ToDB() ([]byte, error) {
  70. return json.Marshal(cfg)
  71. }
  72. // SecurityProtocolName returns the name of configured security
  73. // protocol.
  74. func (cfg *LDAPConfig) SecurityProtocolName() string {
  75. return SecurityProtocolNames[cfg.SecurityProtocol]
  76. }
  77. // SMTPConfig holds configuration for the SMTP login source.
  78. type SMTPConfig struct {
  79. Auth string
  80. Host string
  81. Port int
  82. AllowedDomains string `xorm:"TEXT"`
  83. TLS bool
  84. SkipVerify bool
  85. }
  86. // FromDB fills up an SMTPConfig from serialized format.
  87. func (cfg *SMTPConfig) FromDB(bs []byte) error {
  88. return json.Unmarshal(bs, cfg)
  89. }
  90. // ToDB exports an SMTPConfig to a serialized format.
  91. func (cfg *SMTPConfig) ToDB() ([]byte, error) {
  92. return json.Marshal(cfg)
  93. }
  94. // PAMConfig holds configuration for the PAM login source.
  95. type PAMConfig struct {
  96. ServiceName string // pam service (e.g. system-auth)
  97. }
  98. // FromDB fills up a PAMConfig from serialized format.
  99. func (cfg *PAMConfig) FromDB(bs []byte) error {
  100. return json.Unmarshal(bs, &cfg)
  101. }
  102. // ToDB exports a PAMConfig to a serialized format.
  103. func (cfg *PAMConfig) ToDB() ([]byte, error) {
  104. return json.Marshal(cfg)
  105. }
  106. // OAuth2Config holds configuration for the OAuth2 login source.
  107. type OAuth2Config struct {
  108. Provider string
  109. ClientID string
  110. ClientSecret string
  111. OpenIDConnectAutoDiscoveryURL string
  112. CustomURLMapping *oauth2.CustomURLMapping
  113. }
  114. // FromDB fills up an OAuth2Config from serialized format.
  115. func (cfg *OAuth2Config) FromDB(bs []byte) error {
  116. return json.Unmarshal(bs, cfg)
  117. }
  118. // ToDB exports an SMTPConfig to a serialized format.
  119. func (cfg *OAuth2Config) ToDB() ([]byte, error) {
  120. return json.Marshal(cfg)
  121. }
  122. // SSPIConfig holds configuration for SSPI single sign-on.
  123. type SSPIConfig struct {
  124. AutoCreateUsers bool
  125. AutoActivateUsers bool
  126. StripDomainNames bool
  127. SeparatorReplacement string
  128. DefaultLanguage string
  129. }
  130. // FromDB fills up an SSPIConfig from serialized format.
  131. func (cfg *SSPIConfig) FromDB(bs []byte) error {
  132. return json.Unmarshal(bs, cfg)
  133. }
  134. // ToDB exports an SSPIConfig to a serialized format.
  135. func (cfg *SSPIConfig) ToDB() ([]byte, error) {
  136. return json.Marshal(cfg)
  137. }
  138. // LoginSource represents an external way for authorizing users.
  139. type LoginSource struct {
  140. ID int64 `xorm:"pk autoincr"`
  141. Type LoginType
  142. Name string `xorm:"UNIQUE"`
  143. IsActived bool `xorm:"INDEX NOT NULL DEFAULT false"`
  144. IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
  145. Cfg convert.Conversion `xorm:"TEXT"`
  146. CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
  147. UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
  148. }
  149. // Cell2Int64 converts a xorm.Cell type to int64,
  150. // and handles possible irregular cases.
  151. func Cell2Int64(val xorm.Cell) int64 {
  152. switch (*val).(type) {
  153. case []uint8:
  154. log.Trace("Cell2Int64 ([]uint8): %v", *val)
  155. return com.StrTo(string((*val).([]uint8))).MustInt64()
  156. }
  157. return (*val).(int64)
  158. }
  159. // BeforeSet is invoked from XORM before setting the value of a field of this object.
  160. func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
  161. if colName == "type" {
  162. switch LoginType(Cell2Int64(val)) {
  163. case LoginLDAP, LoginDLDAP:
  164. source.Cfg = new(LDAPConfig)
  165. case LoginSMTP:
  166. source.Cfg = new(SMTPConfig)
  167. case LoginPAM:
  168. source.Cfg = new(PAMConfig)
  169. case LoginOAuth2:
  170. source.Cfg = new(OAuth2Config)
  171. case LoginSSPI:
  172. source.Cfg = new(SSPIConfig)
  173. default:
  174. panic("unrecognized login source type: " + com.ToStr(*val))
  175. }
  176. }
  177. }
  178. // TypeName return name of this login source type.
  179. func (source *LoginSource) TypeName() string {
  180. return LoginNames[source.Type]
  181. }
  182. // IsLDAP returns true of this source is of the LDAP type.
  183. func (source *LoginSource) IsLDAP() bool {
  184. return source.Type == LoginLDAP
  185. }
  186. // IsDLDAP returns true of this source is of the DLDAP type.
  187. func (source *LoginSource) IsDLDAP() bool {
  188. return source.Type == LoginDLDAP
  189. }
  190. // IsSMTP returns true of this source is of the SMTP type.
  191. func (source *LoginSource) IsSMTP() bool {
  192. return source.Type == LoginSMTP
  193. }
  194. // IsPAM returns true of this source is of the PAM type.
  195. func (source *LoginSource) IsPAM() bool {
  196. return source.Type == LoginPAM
  197. }
  198. // IsOAuth2 returns true of this source is of the OAuth2 type.
  199. func (source *LoginSource) IsOAuth2() bool {
  200. return source.Type == LoginOAuth2
  201. }
  202. // IsSSPI returns true of this source is of the SSPI type.
  203. func (source *LoginSource) IsSSPI() bool {
  204. return source.Type == LoginSSPI
  205. }
  206. // HasTLS returns true of this source supports TLS.
  207. func (source *LoginSource) HasTLS() bool {
  208. return ((source.IsLDAP() || source.IsDLDAP()) &&
  209. source.LDAP().SecurityProtocol > ldap.SecurityProtocolUnencrypted) ||
  210. source.IsSMTP()
  211. }
  212. // UseTLS returns true of this source is configured to use TLS.
  213. func (source *LoginSource) UseTLS() bool {
  214. switch source.Type {
  215. case LoginLDAP, LoginDLDAP:
  216. return source.LDAP().SecurityProtocol != ldap.SecurityProtocolUnencrypted
  217. case LoginSMTP:
  218. return source.SMTP().TLS
  219. }
  220. return false
  221. }
  222. // SkipVerify returns true if this source is configured to skip SSL
  223. // verification.
  224. func (source *LoginSource) SkipVerify() bool {
  225. switch source.Type {
  226. case LoginLDAP, LoginDLDAP:
  227. return source.LDAP().SkipVerify
  228. case LoginSMTP:
  229. return source.SMTP().SkipVerify
  230. }
  231. return false
  232. }
  233. // LDAP returns LDAPConfig for this source, if of LDAP type.
  234. func (source *LoginSource) LDAP() *LDAPConfig {
  235. return source.Cfg.(*LDAPConfig)
  236. }
  237. // SMTP returns SMTPConfig for this source, if of SMTP type.
  238. func (source *LoginSource) SMTP() *SMTPConfig {
  239. return source.Cfg.(*SMTPConfig)
  240. }
  241. // PAM returns PAMConfig for this source, if of PAM type.
  242. func (source *LoginSource) PAM() *PAMConfig {
  243. return source.Cfg.(*PAMConfig)
  244. }
  245. // OAuth2 returns OAuth2Config for this source, if of OAuth2 type.
  246. func (source *LoginSource) OAuth2() *OAuth2Config {
  247. return source.Cfg.(*OAuth2Config)
  248. }
  249. // SSPI returns SSPIConfig for this source, if of SSPI type.
  250. func (source *LoginSource) SSPI() *SSPIConfig {
  251. return source.Cfg.(*SSPIConfig)
  252. }
  253. // CreateLoginSource inserts a LoginSource in the DB if not already
  254. // existing with the given name.
  255. func CreateLoginSource(source *LoginSource) error {
  256. has, err := x.Where("name=?", source.Name).Exist(new(LoginSource))
  257. if err != nil {
  258. return err
  259. } else if has {
  260. return ErrLoginSourceAlreadyExist{source.Name}
  261. }
  262. // Synchronization is only aviable with LDAP for now
  263. if !source.IsLDAP() {
  264. source.IsSyncEnabled = false
  265. }
  266. _, err = x.Insert(source)
  267. if err == nil && source.IsOAuth2() && source.IsActived {
  268. oAuth2Config := source.OAuth2()
  269. err = oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping)
  270. err = wrapOpenIDConnectInitializeError(err, source.Name, oAuth2Config)
  271. if err != nil {
  272. // remove the LoginSource in case of errors while registering OAuth2 providers
  273. if _, err := x.Delete(source); err != nil {
  274. log.Error("CreateLoginSource: Error while wrapOpenIDConnectInitializeError: %v", err)
  275. }
  276. return err
  277. }
  278. }
  279. return err
  280. }
  281. // LoginSources returns a slice of all login sources found in DB.
  282. func LoginSources() ([]*LoginSource, error) {
  283. auths := make([]*LoginSource, 0, 6)
  284. return auths, x.Find(&auths)
  285. }
  286. // LoginSourcesByType returns all sources of the specified type
  287. func LoginSourcesByType(loginType LoginType) ([]*LoginSource, error) {
  288. sources := make([]*LoginSource, 0, 1)
  289. if err := x.Where("type = ?", loginType).Find(&sources); err != nil {
  290. return nil, err
  291. }
  292. return sources, nil
  293. }
  294. // ActiveLoginSources returns all active sources of the specified type
  295. func ActiveLoginSources(loginType LoginType) ([]*LoginSource, error) {
  296. sources := make([]*LoginSource, 0, 1)
  297. if err := x.Where("is_actived = ? and type = ?", true, loginType).Find(&sources); err != nil {
  298. return nil, err
  299. }
  300. return sources, nil
  301. }
  302. // IsSSPIEnabled returns true if there is at least one activated login
  303. // source of type LoginSSPI
  304. func IsSSPIEnabled() bool {
  305. if !HasEngine {
  306. return false
  307. }
  308. sources, err := ActiveLoginSources(LoginSSPI)
  309. if err != nil {
  310. log.Error("ActiveLoginSources: %v", err)
  311. return false
  312. }
  313. return len(sources) > 0
  314. }
  315. // GetLoginSourceByID returns login source by given ID.
  316. func GetLoginSourceByID(id int64) (*LoginSource, error) {
  317. source := new(LoginSource)
  318. has, err := x.ID(id).Get(source)
  319. if err != nil {
  320. return nil, err
  321. } else if !has {
  322. return nil, ErrLoginSourceNotExist{id}
  323. }
  324. return source, nil
  325. }
  326. // UpdateSource updates a LoginSource record in DB.
  327. func UpdateSource(source *LoginSource) error {
  328. var originalLoginSource *LoginSource
  329. if source.IsOAuth2() {
  330. // keep track of the original values so we can restore in case of errors while registering OAuth2 providers
  331. var err error
  332. if originalLoginSource, err = GetLoginSourceByID(source.ID); err != nil {
  333. return err
  334. }
  335. }
  336. _, err := x.ID(source.ID).AllCols().Update(source)
  337. if err == nil && source.IsOAuth2() && source.IsActived {
  338. oAuth2Config := source.OAuth2()
  339. err = oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping)
  340. err = wrapOpenIDConnectInitializeError(err, source.Name, oAuth2Config)
  341. if err != nil {
  342. // restore original values since we cannot update the provider it self
  343. if _, err := x.ID(source.ID).AllCols().Update(originalLoginSource); err != nil {
  344. log.Error("UpdateSource: Error while wrapOpenIDConnectInitializeError: %v", err)
  345. }
  346. return err
  347. }
  348. }
  349. return err
  350. }
  351. // DeleteSource deletes a LoginSource record in DB.
  352. func DeleteSource(source *LoginSource) error {
  353. count, err := x.Count(&User{LoginSource: source.ID})
  354. if err != nil {
  355. return err
  356. } else if count > 0 {
  357. return ErrLoginSourceInUse{source.ID}
  358. }
  359. count, err = x.Count(&ExternalLoginUser{LoginSourceID: source.ID})
  360. if err != nil {
  361. return err
  362. } else if count > 0 {
  363. return ErrLoginSourceInUse{source.ID}
  364. }
  365. if source.IsOAuth2() {
  366. oauth2.RemoveProvider(source.Name)
  367. }
  368. _, err = x.ID(source.ID).Delete(new(LoginSource))
  369. return err
  370. }
  371. // CountLoginSources returns number of login sources.
  372. func CountLoginSources() int64 {
  373. count, _ := x.Count(new(LoginSource))
  374. return count
  375. }
  376. // .____ ________ _____ __________
  377. // | | \______ \ / _ \\______ \
  378. // | | | | \ / /_\ \| ___/
  379. // | |___ | ` \/ | \ |
  380. // |_______ \/_______ /\____|__ /____|
  381. // \/ \/ \/
  382. func composeFullName(firstname, surname, username string) string {
  383. switch {
  384. case len(firstname) == 0 && len(surname) == 0:
  385. return username
  386. case len(firstname) == 0:
  387. return surname
  388. case len(surname) == 0:
  389. return firstname
  390. default:
  391. return firstname + " " + surname
  392. }
  393. }
  394. // LoginViaLDAP queries if login/password is valid against the LDAP directory pool,
  395. // and create a local user if success when enabled.
  396. func LoginViaLDAP(user *User, login, password string, source *LoginSource) (*User, error) {
  397. sr := source.Cfg.(*LDAPConfig).SearchEntry(login, password, source.Type == LoginDLDAP)
  398. if sr == nil {
  399. // User not in LDAP, do nothing
  400. return nil, ErrUserNotExist{0, login, 0}
  401. }
  402. var isAttributeSSHPublicKeySet = len(strings.TrimSpace(source.LDAP().AttributeSSHPublicKey)) > 0
  403. // Update User admin flag if exist
  404. if isExist, err := IsUserExist(0, sr.Username); err != nil {
  405. return nil, err
  406. } else if isExist {
  407. if user == nil {
  408. user, err = GetUserByName(sr.Username)
  409. if err != nil {
  410. return nil, err
  411. }
  412. }
  413. if user != nil && !user.ProhibitLogin {
  414. cols := make([]string, 0)
  415. if len(source.LDAP().AdminFilter) > 0 && user.IsAdmin != sr.IsAdmin {
  416. // Change existing admin flag only if AdminFilter option is set
  417. user.IsAdmin = sr.IsAdmin
  418. cols = append(cols, "is_admin")
  419. }
  420. if !user.IsAdmin && len(source.LDAP().RestrictedFilter) > 0 && user.IsRestricted != sr.IsRestricted {
  421. // Change existing restricted flag only if RestrictedFilter option is set
  422. user.IsRestricted = sr.IsRestricted
  423. cols = append(cols, "is_restricted")
  424. }
  425. if len(cols) > 0 {
  426. err = UpdateUserCols(user, cols...)
  427. if err != nil {
  428. return nil, err
  429. }
  430. }
  431. }
  432. }
  433. if user != nil {
  434. if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
  435. return user, RewriteAllPublicKeys()
  436. }
  437. return user, nil
  438. }
  439. // Fallback.
  440. if len(sr.Username) == 0 {
  441. sr.Username = login
  442. }
  443. if len(sr.Mail) == 0 {
  444. sr.Mail = fmt.Sprintf("%s@localhost", sr.Username)
  445. }
  446. user = &User{
  447. LowerName: strings.ToLower(sr.Username),
  448. Name: sr.Username,
  449. FullName: composeFullName(sr.Name, sr.Surname, sr.Username),
  450. Email: sr.Mail,
  451. LoginType: source.Type,
  452. LoginSource: source.ID,
  453. LoginName: login,
  454. IsActive: true,
  455. IsAdmin: sr.IsAdmin,
  456. IsRestricted: sr.IsRestricted,
  457. }
  458. err := CreateUser(user)
  459. if err == nil && isAttributeSSHPublicKeySet && addLdapSSHPublicKeys(user, source, sr.SSHPublicKey) {
  460. err = RewriteAllPublicKeys()
  461. }
  462. return user, err
  463. }
  464. // _________ __________________________
  465. // / _____/ / \__ ___/\______ \
  466. // \_____ \ / \ / \| | | ___/
  467. // / \/ Y \ | | |
  468. // /_______ /\____|__ /____| |____|
  469. // \/ \/
  470. type smtpLoginAuth struct {
  471. username, password string
  472. }
  473. func (auth *smtpLoginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
  474. return "LOGIN", []byte(auth.username), nil
  475. }
  476. func (auth *smtpLoginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
  477. if more {
  478. switch string(fromServer) {
  479. case "Username:":
  480. return []byte(auth.username), nil
  481. case "Password:":
  482. return []byte(auth.password), nil
  483. }
  484. }
  485. return nil, nil
  486. }
  487. // SMTP authentication type names.
  488. const (
  489. SMTPPlain = "PLAIN"
  490. SMTPLogin = "LOGIN"
  491. )
  492. // SMTPAuths contains available SMTP authentication type names.
  493. var SMTPAuths = []string{SMTPPlain, SMTPLogin}
  494. // SMTPAuth performs an SMTP authentication.
  495. func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
  496. c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port))
  497. if err != nil {
  498. return err
  499. }
  500. defer c.Close()
  501. if err = c.Hello("gogs"); err != nil {
  502. return err
  503. }
  504. if cfg.TLS {
  505. if ok, _ := c.Extension("STARTTLS"); ok {
  506. if err = c.StartTLS(&tls.Config{
  507. InsecureSkipVerify: cfg.SkipVerify,
  508. ServerName: cfg.Host,
  509. }); err != nil {
  510. return err
  511. }
  512. } else {
  513. return errors.New("SMTP server unsupports TLS")
  514. }
  515. }
  516. if ok, _ := c.Extension("AUTH"); ok {
  517. return c.Auth(a)
  518. }
  519. return ErrUnsupportedLoginType
  520. }
  521. // LoginViaSMTP queries if login/password is valid against the SMTP,
  522. // and create a local user if success when enabled.
  523. func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPConfig) (*User, error) {
  524. // Verify allowed domains.
  525. if len(cfg.AllowedDomains) > 0 {
  526. idx := strings.Index(login, "@")
  527. if idx == -1 {
  528. return nil, ErrUserNotExist{0, login, 0}
  529. } else if !com.IsSliceContainsStr(strings.Split(cfg.AllowedDomains, ","), login[idx+1:]) {
  530. return nil, ErrUserNotExist{0, login, 0}
  531. }
  532. }
  533. var auth smtp.Auth
  534. if cfg.Auth == SMTPPlain {
  535. auth = smtp.PlainAuth("", login, password, cfg.Host)
  536. } else if cfg.Auth == SMTPLogin {
  537. auth = &smtpLoginAuth{login, password}
  538. } else {
  539. return nil, errors.New("Unsupported SMTP auth type")
  540. }
  541. if err := SMTPAuth(auth, cfg); err != nil {
  542. // Check standard error format first,
  543. // then fallback to worse case.
  544. tperr, ok := err.(*textproto.Error)
  545. if (ok && tperr.Code == 535) ||
  546. strings.Contains(err.Error(), "Username and Password not accepted") {
  547. return nil, ErrUserNotExist{0, login, 0}
  548. }
  549. return nil, err
  550. }
  551. if user != nil {
  552. return user, nil
  553. }
  554. username := login
  555. idx := strings.Index(login, "@")
  556. if idx > -1 {
  557. username = login[:idx]
  558. }
  559. user = &User{
  560. LowerName: strings.ToLower(username),
  561. Name: strings.ToLower(username),
  562. Email: login,
  563. Passwd: password,
  564. LoginType: LoginSMTP,
  565. LoginSource: sourceID,
  566. LoginName: login,
  567. IsActive: true,
  568. }
  569. return user, CreateUser(user)
  570. }
  571. // __________ _____ _____
  572. // \______ \/ _ \ / \
  573. // | ___/ /_\ \ / \ / \
  574. // | | / | \/ Y \
  575. // |____| \____|__ /\____|__ /
  576. // \/ \/
  577. // LoginViaPAM queries if login/password is valid against the PAM,
  578. // and create a local user if success when enabled.
  579. func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMConfig) (*User, error) {
  580. pamLogin, err := pam.Auth(cfg.ServiceName, login, password)
  581. if err != nil {
  582. if strings.Contains(err.Error(), "Authentication failure") {
  583. return nil, ErrUserNotExist{0, login, 0}
  584. }
  585. return nil, err
  586. }
  587. if user != nil {
  588. return user, nil
  589. }
  590. // Allow PAM sources with `@` in their name, like from Active Directory
  591. username := pamLogin
  592. idx := strings.Index(pamLogin, "@")
  593. if idx > -1 {
  594. username = pamLogin[:idx]
  595. }
  596. user = &User{
  597. LowerName: strings.ToLower(username),
  598. Name: username,
  599. Email: pamLogin,
  600. Passwd: password,
  601. LoginType: LoginPAM,
  602. LoginSource: sourceID,
  603. LoginName: login, // This is what the user typed in
  604. IsActive: true,
  605. }
  606. return user, CreateUser(user)
  607. }
  608. // ExternalUserLogin attempts a login using external source types.
  609. func ExternalUserLogin(user *User, login, password string, source *LoginSource) (*User, error) {
  610. if !source.IsActived {
  611. return nil, ErrLoginSourceNotActived
  612. }
  613. var err error
  614. switch source.Type {
  615. case LoginLDAP, LoginDLDAP:
  616. user, err = LoginViaLDAP(user, login, password, source)
  617. case LoginSMTP:
  618. user, err = LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig))
  619. case LoginPAM:
  620. user, err = LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig))
  621. default:
  622. return nil, ErrUnsupportedLoginType
  623. }
  624. if err != nil {
  625. return nil, err
  626. }
  627. // WARN: DON'T check user.IsActive, that will be checked on reqSign so that
  628. // user could be hint to resend confirm email.
  629. if user.ProhibitLogin {
  630. return nil, ErrUserProhibitLogin{user.ID, user.Name}
  631. }
  632. return user, nil
  633. }
  634. // UserSignIn validates user name and password.
  635. func UserSignIn(username, password string) (*User, error) {
  636. var user *User
  637. if strings.Contains(username, "@") {
  638. user = &User{Email: strings.ToLower(strings.TrimSpace(username))}
  639. // check same email
  640. cnt, err := x.Count(user)
  641. if err != nil {
  642. return nil, err
  643. }
  644. if cnt > 1 {
  645. return nil, ErrEmailAlreadyUsed{
  646. Email: user.Email,
  647. }
  648. }
  649. } else {
  650. trimmedUsername := strings.TrimSpace(username)
  651. if len(trimmedUsername) == 0 {
  652. return nil, ErrUserNotExist{0, username, 0}
  653. }
  654. user = &User{LowerName: strings.ToLower(trimmedUsername)}
  655. }
  656. hasUser, err := x.Get(user)
  657. if err != nil {
  658. return nil, err
  659. }
  660. if hasUser {
  661. switch user.LoginType {
  662. case LoginNoType, LoginPlain, LoginOAuth2:
  663. if user.IsPasswordSet() && user.ValidatePassword(password) {
  664. // Update password hash if server password hash algorithm have changed
  665. if user.PasswdHashAlgo != setting.PasswordHashAlgo {
  666. user.HashPassword(password)
  667. if err := UpdateUserCols(user, "passwd", "passwd_hash_algo"); err != nil {
  668. return nil, err
  669. }
  670. }
  671. // WARN: DON'T check user.IsActive, that will be checked on reqSign so that
  672. // user could be hint to resend confirm email.
  673. if user.ProhibitLogin {
  674. return nil, ErrUserProhibitLogin{user.ID, user.Name}
  675. }
  676. return user, nil
  677. }
  678. return nil, ErrUserNotExist{user.ID, user.Name, 0}
  679. default:
  680. var source LoginSource
  681. hasSource, err := x.ID(user.LoginSource).Get(&source)
  682. if err != nil {
  683. return nil, err
  684. } else if !hasSource {
  685. return nil, ErrLoginSourceNotExist{user.LoginSource}
  686. }
  687. return ExternalUserLogin(user, user.LoginName, password, &source)
  688. }
  689. }
  690. sources := make([]*LoginSource, 0, 5)
  691. if err = x.Where("is_actived = ?", true).Find(&sources); err != nil {
  692. return nil, err
  693. }
  694. for _, source := range sources {
  695. if source.IsOAuth2() || source.IsSSPI() {
  696. // don't try to authenticate against OAuth2 and SSPI sources here
  697. continue
  698. }
  699. authUser, err := ExternalUserLogin(nil, username, password, source)
  700. if err == nil {
  701. return authUser, nil
  702. }
  703. log.Warn("Failed to login '%s' via '%s': %v", username, source.Name, err)
  704. }
  705. return nil, ErrUserNotExist{user.ID, user.Name, 0}
  706. }