summaryrefslogtreecommitdiffstats
path: root/gerrit-openid
diff options
context:
space:
mode:
authorDave Borowitz <dborowitz@google.com>2012-01-20 14:05:59 -0800
committerShawn O. Pearce <sop@google.com>2012-01-23 15:36:09 -0800
commitfb6196708160e06a2215abfeb55a4773e3223fb3 (patch)
tree16b91fc61a8817ef2055c721f9d77595e6b47291 /gerrit-openid
parentad3209eebfa53e4cb095ad0c4adc9e611e7f60f9 (diff)
Extract OpenID RPC implementation into its own module
This avoids a dependency on openid4java for users that don't need OpenID support. Change-Id: I8dfce1e32f145aebed5e6c1d01c77872528ab43f
Diffstat (limited to 'gerrit-openid')
-rw-r--r--gerrit-openid/.gitignore5
-rw-r--r--gerrit-openid/.settings/org.eclipse.core.resources.prefs5
-rw-r--r--gerrit-openid/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--gerrit-openid/.settings/org.eclipse.jdt.core.prefs269
-rw-r--r--gerrit-openid/.settings/org.eclipse.jdt.ui.prefs61
-rw-r--r--gerrit-openid/pom.xml91
-rw-r--r--gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdLoginServlet.java57
-rw-r--r--gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdModule.java35
-rw-r--r--gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java554
-rw-r--r--gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsFilter.java42
-rw-r--r--gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java72
11 files changed, 1194 insertions, 0 deletions
diff --git a/gerrit-openid/.gitignore b/gerrit-openid/.gitignore
new file mode 100644
index 0000000000..194bedcbc4
--- /dev/null
+++ b/gerrit-openid/.gitignore
@@ -0,0 +1,5 @@
+/target
+/.classpath
+/.project
+/.settings/org.maven.ide.eclipse.prefs
+/.settings/org.eclipse.m2e.core.prefs \ No newline at end of file
diff --git a/gerrit-openid/.settings/org.eclipse.core.resources.prefs b/gerrit-openid/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000000..fc11c3fe6f
--- /dev/null
+++ b/gerrit-openid/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+#Thu Jul 28 11:02:36 PDT 2011
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8
diff --git a/gerrit-openid/.settings/org.eclipse.core.runtime.prefs b/gerrit-openid/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000000..8667cfd4a3
--- /dev/null
+++ b/gerrit-openid/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Sep 02 16:59:24 PDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/gerrit-openid/.settings/org.eclipse.jdt.core.prefs b/gerrit-openid/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..470942d4f6
--- /dev/null
+++ b/gerrit-openid/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,269 @@
+#Thu Jul 28 11:02:36 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=16
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/gerrit-openid/.settings/org.eclipse.jdt.ui.prefs b/gerrit-openid/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000..d4218a5fc0
--- /dev/null
+++ b/gerrit-openid/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Wed Jul 29 11:31:38 PDT 2009
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_Google Format
+formatter_settings_version=11
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=com.google;com;junit;net;org;java;javax;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/gerrit-openid/pom.xml b/gerrit-openid/pom.xml
new file mode 100644
index 0000000000..310bd1aebd
--- /dev/null
+++ b/gerrit-openid/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2009 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>com.google.gerrit</groupId>
+ <artifactId>gerrit-parent</artifactId>
+ <version>2.2-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>gerrit-openid</artifactId>
+ <name>Gerrit Code Review - OpenID servlet and RPC</name>
+
+ <description>
+ OpenID
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit.http.server</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.gwt</groupId>
+ <artifactId>gwt-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.openid4java</groupId>
+ <artifactId>openid4java-consumer</artifactId>
+ <type>pom</type>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.gerrit</groupId>
+ <artifactId>gerrit-httpd</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.gerrit</groupId>
+ <artifactId>gerrit-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdLoginServlet.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdLoginServlet.java
new file mode 100644
index 0000000000..cfb767d0ba
--- /dev/null
+++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdLoginServlet.java
@@ -0,0 +1,57 @@
+// Copyright (C) 2008 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.auth.openid;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** Handles the <code>/OpenID</code> URL for web based single-sign-on. */
+@SuppressWarnings("serial")
+@Singleton
+class OpenIdLoginServlet extends HttpServlet {
+ private final OpenIdServiceImpl impl;
+
+ @Inject
+ OpenIdLoginServlet(final OpenIdServiceImpl i) {
+ impl = i;
+ }
+
+ @Override
+ public void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
+ throws IOException {
+ doPost(req, rsp);
+ }
+
+ @Override
+ public void doPost(final HttpServletRequest req, final HttpServletResponse rsp)
+ throws IOException {
+ try {
+ rsp.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
+ rsp.setHeader("Pragma", "no-cache");
+ rsp.setHeader("Cache-Control", "no-cache, must-revalidate");
+ impl.doAuth(req, rsp);
+ } catch (Exception e) {
+ getServletContext().log("Unexpected error during authentication", e);
+ rsp.reset();
+ rsp.sendError(500);
+ }
+ }
+}
diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdModule.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdModule.java
new file mode 100644
index 0000000000..a928cb8536
--- /dev/null
+++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdModule.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.auth.openid;
+
+import com.google.gerrit.httpd.rpc.RpcServletModule;
+import com.google.inject.servlet.ServletModule;
+
+/** Servlets and RPC support related to OpenID authentication. */
+public class OpenIdModule extends ServletModule {
+ @Override
+ protected void configureServlets() {
+ serve("/" + OpenIdServiceImpl.RETURN_URL).with(OpenIdLoginServlet.class);
+ serve("/" + XrdsServlet.LOCATION).with(XrdsServlet.class);
+ filter("/").through(XrdsFilter.class);
+
+ install(new RpcServletModule(RpcServletModule.PREFIX) {
+ @Override
+ protected void configureServlets() {
+ rpc(OpenIdServiceImpl.class);
+ }
+ });
+ }
+}
diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
new file mode 100644
index 0000000000..02ef7657e2
--- /dev/null
+++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
@@ -0,0 +1,554 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.auth.openid;
+
+import com.google.gerrit.common.PageLinks;
+import com.google.gerrit.common.auth.SignInMode;
+import com.google.gerrit.common.auth.openid.DiscoveryResult;
+import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
+import com.google.gerrit.common.auth.openid.OpenIdService;
+import com.google.gerrit.common.auth.openid.OpenIdUrls;
+import com.google.gerrit.httpd.WebSession;
+import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.UrlEncoded;
+import com.google.gerrit.server.account.AccountException;
+import com.google.gerrit.server.account.AccountManager;
+import com.google.gerrit.server.config.AuthConfig;
+import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.gerrit.server.config.ConfigUtil;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtorm.client.KeyUtil;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lib.Config;
+import org.openid4java.consumer.ConsumerException;
+import org.openid4java.consumer.ConsumerManager;
+import org.openid4java.consumer.VerificationResult;
+import org.openid4java.discovery.DiscoveryException;
+import org.openid4java.discovery.DiscoveryInformation;
+import org.openid4java.message.AuthRequest;
+import org.openid4java.message.Message;
+import org.openid4java.message.MessageException;
+import org.openid4java.message.MessageExtension;
+import org.openid4java.message.ParameterList;
+import org.openid4java.message.ax.AxMessage;
+import org.openid4java.message.ax.FetchRequest;
+import org.openid4java.message.ax.FetchResponse;
+import org.openid4java.message.pape.PapeMessage;
+import org.openid4java.message.pape.PapeRequest;
+import org.openid4java.message.pape.PapeResponse;
+import org.openid4java.message.sreg.SRegMessage;
+import org.openid4java.message.sreg.SRegRequest;
+import org.openid4java.message.sreg.SRegResponse;
+import org.openid4java.util.HttpClientFactory;
+import org.openid4java.util.ProxyProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Singleton
+class OpenIdServiceImpl implements OpenIdService {
+ private static final Logger log =
+ LoggerFactory.getLogger(OpenIdServiceImpl.class);
+
+ static final String RETURN_URL = "OpenID";
+
+ private static final String P_MODE = "gerrit.mode";
+ private static final String P_TOKEN = "gerrit.token";
+ private static final String P_REMEMBER = "gerrit.remember";
+ private static final String P_CLAIMED = "gerrit.claimed";
+ private static final int LASTID_AGE = 365 * 24 * 60 * 60; // seconds
+
+ private static final String OPENID_MODE = "openid.mode";
+ private static final String OMODE_CANCEL = "cancel";
+
+ private static final String SCHEMA_EMAIL =
+ "http://schema.openid.net/contact/email";
+ private static final String SCHEMA_FIRSTNAME =
+ "http://schema.openid.net/namePerson/first";
+ private static final String SCHEMA_LASTNAME =
+ "http://schema.openid.net/namePerson/last";
+
+ private final Provider<WebSession> webSession;
+ private final Provider<IdentifiedUser> identifiedUser;
+ private final Provider<String> urlProvider;
+ private final AccountManager accountManager;
+ private final ConsumerManager manager;
+ private final List<OpenIdProviderPattern> allowedOpenIDs;
+
+ /** Maximum age, in seconds, before forcing re-authentication of account. */
+ private final int papeMaxAuthAge;
+
+ @Inject
+ OpenIdServiceImpl(final Provider<WebSession> cf,
+ final Provider<IdentifiedUser> iu,
+ @CanonicalWebUrl @Nullable final Provider<String> up,
+ @GerritServerConfig final Config config, final AuthConfig ac,
+ final AccountManager am) throws ConsumerException, MalformedURLException {
+
+ if (config.getString("http", null, "proxy") != null) {
+ final URL proxyUrl = new URL(config.getString("http", null, "proxy"));
+ String username = config.getString("http", null, "proxyUsername");
+ String password = config.getString("http", null, "proxyPassword");
+
+ final String userInfo = proxyUrl.getUserInfo();
+ if (userInfo != null) {
+ int c = userInfo.indexOf(':');
+ if (0 < c) {
+ username = userInfo.substring(0, c);
+ password = userInfo.substring(c + 1);
+ } else {
+ username = userInfo;
+ }
+ }
+
+ final ProxyProperties proxy = new ProxyProperties();
+ proxy.setProxyHostName(proxyUrl.getHost());
+ proxy.setProxyPort(proxyUrl.getPort());
+ proxy.setUserName(username);
+ proxy.setPassword(password);
+ HttpClientFactory.setProxyProperties(proxy);
+ }
+
+ webSession = cf;
+ identifiedUser = iu;
+ urlProvider = up;
+ accountManager = am;
+ manager = new ConsumerManager();
+ allowedOpenIDs = ac.getAllowedOpenIDs();
+ papeMaxAuthAge = (int) ConfigUtil.getTimeUnit(config, //
+ "auth", null, "maxOpenIdSessionAge", -1, TimeUnit.SECONDS);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void discover(final String openidIdentifier, final SignInMode mode,
+ final boolean remember, final String returnToken,
+ final AsyncCallback<DiscoveryResult> cb) {
+ if (!isAllowedOpenID(openidIdentifier)) {
+ cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.NOT_ALLOWED));
+ return;
+ }
+
+ final State state;
+ state = init(openidIdentifier, mode, remember, returnToken);
+ if (state == null) {
+ cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.NO_PROVIDER));
+ return;
+ }
+
+ final AuthRequest aReq;
+ try {
+ aReq = manager.authenticate(state.discovered, state.retTo.toString());
+ aReq.setRealm(state.contextUrl);
+
+ if (requestRegistration(aReq)) {
+ final SRegRequest sregReq = SRegRequest.createFetchRequest();
+ sregReq.addAttribute("fullname", true);
+ sregReq.addAttribute("email", true);
+ aReq.addExtension(sregReq);
+
+ final FetchRequest fetch = FetchRequest.createFetchRequest();
+ fetch.addAttribute("FirstName", SCHEMA_FIRSTNAME, true);
+ fetch.addAttribute("LastName", SCHEMA_LASTNAME, true);
+ fetch.addAttribute("Email", SCHEMA_EMAIL, true);
+ aReq.addExtension(fetch);
+ }
+
+ if (0 <= papeMaxAuthAge) {
+ final PapeRequest pape = PapeRequest.createPapeRequest();
+ pape.setMaxAuthAge(papeMaxAuthAge);
+ aReq.addExtension(pape);
+ }
+ } catch (MessageException e) {
+ log.error("Cannot create OpenID redirect for " + openidIdentifier, e);
+ cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.ERROR));
+ return;
+ } catch (ConsumerException e) {
+ log.error("Cannot create OpenID redirect for " + openidIdentifier, e);
+ cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.ERROR));
+ return;
+ }
+
+ cb.onSuccess(new DiscoveryResult(aReq.getDestinationUrl(false), //
+ aReq.getParameterMap()));
+ }
+
+ private boolean requestRegistration(final AuthRequest aReq) {
+ if (AuthRequest.SELECT_ID.equals(aReq.getIdentity())) {
+ // We don't know anything about the identity, as the provider
+ // will offer the user a way to indicate their identity. Skip
+ // any database query operation and assume we must ask for the
+ // registration information, in case the identity is new to us.
+ //
+ return true;
+
+ }
+
+ // We might already have this account on file. Look for it.
+ //
+ try {
+ return accountManager.lookup(aReq.getIdentity()) == null;
+ } catch (AccountException e) {
+ log.warn("Cannot determine if user account exists", e);
+ return true;
+ }
+ }
+
+ /** Called by {@link OpenIdLoginServlet} doGet, doPost */
+ void doAuth(final HttpServletRequest req, final HttpServletResponse rsp)
+ throws Exception {
+ if (OMODE_CANCEL.equals(req.getParameter(OPENID_MODE))) {
+ cancel(req, rsp);
+ return;
+ }
+
+ // Process the authentication response.
+ //
+ final SignInMode mode = signInMode(req);
+ final String openidIdentifier = req.getParameter("openid.identity");
+ final String claimedIdentifier = req.getParameter(P_CLAIMED);
+ final String returnToken = req.getParameter(P_TOKEN);
+ final boolean remember = "1".equals(req.getParameter(P_REMEMBER));
+ final String rediscoverIdentifier =
+ claimedIdentifier != null ? claimedIdentifier : openidIdentifier;
+ final State state;
+
+ if (!isAllowedOpenID(rediscoverIdentifier)
+ || !isAllowedOpenID(openidIdentifier)
+ || (claimedIdentifier != null && !isAllowedOpenID(claimedIdentifier))) {
+ cancelWithError(req, rsp, "Provider not allowed");
+ return;
+ }
+
+ state = init(rediscoverIdentifier, mode, remember, returnToken);
+ if (state == null) {
+ // Re-discovery must have failed, we can't run a login.
+ //
+ cancel(req, rsp);
+ return;
+ }
+
+ final String returnTo = req.getParameter("openid.return_to");
+ if (returnTo != null && returnTo.contains("openid.rpnonce=")) {
+ // Some providers (claimid.com) seem to embed these request
+ // parameters into our return_to URL, and then give us them
+ // in the return_to request parameter. But not all.
+ //
+ state.retTo.put("openid.rpnonce", req.getParameter("openid.rpnonce"));
+ state.retTo.put("openid.rpsig", req.getParameter("openid.rpsig"));
+ }
+
+ final VerificationResult result =
+ manager.verify(state.retTo.toString(), new ParameterList(req
+ .getParameterMap()), state.discovered);
+ if (result.getVerifiedId() == null /* authentication failure */) {
+ if ("Nonce verification failed.".equals(result.getStatusMsg())) {
+ // We might be suffering from clock skew on this system.
+ //
+ log.error("OpenID failure: " + result.getStatusMsg()
+ + " Likely caused by clock skew on this server,"
+ + " install/configure NTP.");
+ cancelWithError(req, rsp, result.getStatusMsg());
+
+ } else if (result.getStatusMsg() != null) {
+ // Authentication failed.
+ //
+ log.error("OpenID failure: " + result.getStatusMsg());
+ cancelWithError(req, rsp, result.getStatusMsg());
+
+ } else {
+ // Assume authentication was canceled.
+ //
+ cancel(req, rsp);
+ }
+ return;
+ }
+
+ final Message authRsp = result.getAuthResponse();
+ SRegResponse sregRsp = null;
+ FetchResponse fetchRsp = null;
+
+ if (0 <= papeMaxAuthAge) {
+ PapeResponse ext;
+ boolean unsupported = false;
+
+ try {
+ ext = (PapeResponse) authRsp.getExtension(PapeMessage.OPENID_NS_PAPE);
+ } catch (MessageException err) {
+ // Far too many providers are unable to provide PAPE extensions
+ // right now. Instead of blocking all of them log the error and
+ // let the authentication complete anyway.
+ //
+ log.error("Invalid PAPE response " + openidIdentifier + ": " + err);
+ unsupported = true;
+ ext = null;
+ }
+ if (!unsupported && ext == null) {
+ log.error("No PAPE extension response from " + openidIdentifier);
+ cancelWithError(req, rsp, "OpenID provider does not support PAPE.");
+ return;
+ }
+ }
+
+ if (authRsp.hasExtension(SRegMessage.OPENID_NS_SREG)) {
+ final MessageExtension ext =
+ authRsp.getExtension(SRegMessage.OPENID_NS_SREG);
+ if (ext instanceof SRegResponse) {
+ sregRsp = (SRegResponse) ext;
+ }
+ }
+
+ if (authRsp.hasExtension(AxMessage.OPENID_NS_AX)) {
+ final MessageExtension ext = authRsp.getExtension(AxMessage.OPENID_NS_AX);
+ if (ext instanceof FetchResponse) {
+ fetchRsp = (FetchResponse) ext;
+ }
+ }
+
+ final com.google.gerrit.server.account.AuthRequest areq =
+ new com.google.gerrit.server.account.AuthRequest(openidIdentifier);
+
+ if (sregRsp != null) {
+ areq.setDisplayName(sregRsp.getAttributeValue("fullname"));
+ areq.setEmailAddress(sregRsp.getAttributeValue("email"));
+
+ } else if (fetchRsp != null) {
+ final String firstName = fetchRsp.getAttributeValue("FirstName");
+ final String lastName = fetchRsp.getAttributeValue("LastName");
+ final StringBuilder n = new StringBuilder();
+ if (firstName != null && firstName.length() > 0) {
+ n.append(firstName);
+ }
+ if (lastName != null && lastName.length() > 0) {
+ if (n.length() > 0) {
+ n.append(' ');
+ }
+ n.append(lastName);
+ }
+ areq.setDisplayName(n.length() > 0 ? n.toString() : null);
+ areq.setEmailAddress(fetchRsp.getAttributeValue("Email"));
+ }
+
+ if (claimedIdentifier != null) {
+ // The user used a claimed identity which has delegated to the verified
+ // identity we have in our AuthRequest above. We still should have a
+ // link between the two, so set one up if not present.
+ //
+ Account.Id claimedId = accountManager.lookup(claimedIdentifier);
+ Account.Id actualId = accountManager.lookup(areq.getExternalId());
+
+ if (claimedId != null && actualId != null) {
+ if (claimedId.equals(actualId)) {
+ // Both link to the same account, that's what we expected.
+ } else {
+ // This is (for now) a fatal error. There are two records
+ // for what might be the same user.
+ //
+ log.error("OpenID accounts disagree over user identity:\n"
+ + " Claimed ID: " + claimedId + " is " + claimedIdentifier
+ + "\n" + " Delgate ID: " + actualId + " is "
+ + areq.getExternalId());
+ cancelWithError(req, rsp, "Contact site administrator");
+ return;
+ }
+
+ } else if (claimedId == null && actualId != null) {
+ // Older account, the actual was already created but the claimed
+ // was missing due to a bug in Gerrit. Link the claimed.
+ //
+ final com.google.gerrit.server.account.AuthRequest linkReq =
+ new com.google.gerrit.server.account.AuthRequest(claimedIdentifier);
+ linkReq.setDisplayName(areq.getDisplayName());
+ linkReq.setEmailAddress(areq.getEmailAddress());
+ accountManager.link(actualId, linkReq);
+
+ } else if (claimedId != null && actualId == null) {
+ // Claimed account already exists, but it smells like the user has
+ // changed their delegate to point to a different provider. Link
+ // the new provider.
+ //
+ accountManager.link(claimedId, areq);
+
+ } else {
+ // Both are null, we are going to create a new account below.
+ }
+ }
+
+ try {
+ final com.google.gerrit.server.account.AuthResult arsp;
+ switch (mode) {
+ case REGISTER:
+ case SIGN_IN:
+ arsp = accountManager.authenticate(areq);
+
+ final Cookie lastId = new Cookie(OpenIdUrls.LASTID_COOKIE, "");
+ lastId.setPath(req.getContextPath() + "/");
+ if (remember) {
+ lastId.setValue(rediscoverIdentifier);
+ lastId.setMaxAge(LASTID_AGE);
+ } else {
+ lastId.setMaxAge(0);
+ }
+ rsp.addCookie(lastId);
+ webSession.get().login(arsp, remember);
+ if (arsp.isNew() && claimedIdentifier != null) {
+ final com.google.gerrit.server.account.AuthRequest linkReq =
+ new com.google.gerrit.server.account.AuthRequest(
+ claimedIdentifier);
+ linkReq.setDisplayName(areq.getDisplayName());
+ linkReq.setEmailAddress(areq.getEmailAddress());
+ accountManager.link(arsp.getAccountId(), linkReq);
+ }
+ callback(arsp.isNew(), req, rsp);
+ break;
+
+ case LINK_IDENTIY: {
+ arsp = accountManager.link(identifiedUser.get().getAccountId(), areq);
+ webSession.get().login(arsp, remember);
+ callback(false, req, rsp);
+ break;
+ }
+ }
+ } catch (AccountException e) {
+ log.error("OpenID authentication failure", e);
+ cancelWithError(req, rsp, "Contact site administrator");
+ }
+ }
+
+ private boolean isSignIn(final SignInMode mode) {
+ switch (mode) {
+ case SIGN_IN:
+ case REGISTER:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static SignInMode signInMode(final HttpServletRequest req) {
+ try {
+ return SignInMode.valueOf(req.getParameter(P_MODE));
+ } catch (RuntimeException e) {
+ return SignInMode.SIGN_IN;
+ }
+ }
+
+ private void callback(final boolean isNew, final HttpServletRequest req,
+ final HttpServletResponse rsp) throws IOException {
+ String token = req.getParameter(P_TOKEN);
+ if (token == null || token.isEmpty() || token.startsWith("/SignInFailure,")) {
+ token = PageLinks.MINE;
+ }
+
+ final StringBuilder rdr = new StringBuilder();
+ rdr.append(urlProvider.get());
+ rdr.append('#');
+ if (isNew && !token.startsWith(PageLinks.REGISTER + "/")) {
+ rdr.append(PageLinks.REGISTER);
+ }
+ rdr.append(token);
+ rsp.sendRedirect(rdr.toString());
+ }
+
+ private void cancel(final HttpServletRequest req,
+ final HttpServletResponse rsp) throws IOException {
+ if (isSignIn(signInMode(req))) {
+ webSession.get().logout();
+ }
+ callback(false, req, rsp);
+ }
+
+ private void cancelWithError(final HttpServletRequest req,
+ final HttpServletResponse rsp, final String errorDetail)
+ throws IOException {
+ final SignInMode mode = signInMode(req);
+ if (isSignIn(mode)) {
+ webSession.get().logout();
+ }
+ final StringBuilder rdr = new StringBuilder();
+ rdr.append(urlProvider.get());
+ rdr.append('#');
+ rdr.append("SignInFailure");
+ rdr.append(',');
+ rdr.append(mode.name());
+ rdr.append(',');
+ rdr.append(errorDetail != null ? KeyUtil.encode(errorDetail) : "");
+ rsp.sendRedirect(rdr.toString());
+ }
+
+ private State init(final String openidIdentifier, final SignInMode mode,
+ final boolean remember, final String returnToken) {
+ final List<?> list;
+ try {
+ list = manager.discover(openidIdentifier);
+ } catch (DiscoveryException e) {
+ log.error("Cannot discover OpenID " + openidIdentifier, e);
+ return null;
+ }
+ if (list == null || list.isEmpty()) {
+ return null;
+ }
+
+ final String contextUrl = urlProvider.get();
+ final DiscoveryInformation discovered = manager.associate(list);
+ final UrlEncoded retTo = new UrlEncoded(contextUrl + RETURN_URL);
+ retTo.put(P_MODE, mode.name());
+ if (returnToken != null && returnToken.length() > 0) {
+ retTo.put(P_TOKEN, returnToken);
+ }
+ if (remember) {
+ retTo.put(P_REMEMBER, "1");
+ }
+ if (discovered.hasClaimedIdentifier()) {
+ retTo.put(P_CLAIMED, discovered.getClaimedIdentifier().getIdentifier());
+ }
+ return new State(discovered, retTo, contextUrl);
+ }
+
+ private boolean isAllowedOpenID(final String id) {
+ for (final OpenIdProviderPattern pattern : allowedOpenIDs) {
+ if (pattern.matches(id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static class State {
+ final DiscoveryInformation discovered;
+ final UrlEncoded retTo;
+ final String contextUrl;
+
+ State(final DiscoveryInformation d, final UrlEncoded r, final String c) {
+ discovered = d;
+ retTo = r;
+ contextUrl = c;
+ }
+ }
+}
diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsFilter.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsFilter.java
new file mode 100644
index 0000000000..92230f687d
--- /dev/null
+++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsFilter.java
@@ -0,0 +1,42 @@
+package com.google.gerrit.httpd.auth.openid;
+
+import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+@Singleton
+class XrdsFilter implements Filter {
+ private final Provider<String> url;
+
+ @Inject
+ XrdsFilter(@CanonicalWebUrl final Provider<String> url) {
+ this.url = url;
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ HttpServletResponse rsp = (HttpServletResponse) response;
+ rsp.setHeader("X-XRDS-Location", url.get() + XrdsServlet.LOCATION);
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void init(FilterConfig config) {
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java
new file mode 100644
index 0000000000..98ad11d4b9
--- /dev/null
+++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java
@@ -0,0 +1,72 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.auth.openid;
+
+import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+import java.io.IOException;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Singleton
+class XrdsServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+ private static final String ENC = "UTF-8";
+ static final String LOCATION = "OpenID.XRDS";
+
+ private final Provider<String> url;
+
+ @Inject
+ XrdsServlet(@CanonicalWebUrl final Provider<String> url) {
+ this.url = url;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse rsp)
+ throws IOException {
+ final StringBuilder r = new StringBuilder();
+ r.append("<?xml version=\"1.0\" encoding=\"" + ENC + "\"?>");
+ r.append("<xrds:XRDS");
+ r.append(" xmlns:xrds=\"xri://$xrds\"");
+ r.append(" xmlns:openid=\"http://openid.net/xmlns/1.0\"");
+ r.append(" xmlns=\"xri://$xrd*($v*2.0)\">");
+ r.append("<XRD>");
+ r.append("<Service priority=\"1\">");
+ r.append("<Type>http://specs.openid.net/auth/2.0/return_to</Type>");
+ r.append("<URI>" + url.get() + OpenIdServiceImpl.RETURN_URL + "</URI>");
+ r.append("</Service>");
+ r.append("</XRD>");
+ r.append("</xrds:XRDS>");
+ r.append("\n");
+
+ final byte[] raw = r.toString().getBytes(ENC);
+ rsp.setContentLength(raw.length);
+ rsp.setContentType("application/xrds+xml");
+ rsp.setCharacterEncoding(ENC);
+
+ final ServletOutputStream out = rsp.getOutputStream();
+ try {
+ out.write(raw);
+ } finally {
+ out.close();
+ }
+ }
+}