Skip to content

Commit f4d9d0d

Browse files
committed
Document @AuthenticationPrincipal meta-annotations
Issue gh-15286
1 parent 9aaf959 commit f4d9d0d

File tree

1 file changed

+120
-0
lines changed
  • docs/modules/ROOT/pages/servlet/integrations

1 file changed

+120
-0
lines changed

docs/modules/ROOT/pages/servlet/integrations/mvc.adoc

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,126 @@ open fun findMessagesForUser(@CurrentUser customUser: CustomUser?): ModelAndView
503503
----
504504
======
505505

506+
Once it is a meta-annotation, parameterization is also available to you.
507+
508+
For example, consider when you have a JWT as your principal and you want to say which claim to retrieve.
509+
As a meta-annotation, you might do:
510+
511+
[tabs]
512+
======
513+
Java::
514+
+
515+
[source,java,role="primary"]
516+
----
517+
@Target({ElementType.PARAMETER, ElementType.TYPE})
518+
@Retention(RetentionPolicy.RUNTIME)
519+
@Documented
520+
@AuthenticationPrincipal(expression = "claims['sub']")
521+
public @interface CurrentUser {}
522+
----
523+
524+
Kotlin::
525+
+
526+
[source,kotlin,role="secondary"]
527+
----
528+
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
529+
@Retention(AnnotationRetention.RUNTIME)
530+
@MustBeDocumented
531+
@AuthenticationPrincipal(expression = "claims['sub']")
532+
annotation class CurrentUser
533+
----
534+
======
535+
536+
which is already quite powerful.
537+
But, it is also limited to retrieving the `sub` claim.
538+
539+
To make this more flexible, first publish the `AnnotationTemplateExpressionDefaults` bean like so:
540+
541+
[tabs]
542+
======
543+
Java::
544+
+
545+
[source,java,role="primary"]
546+
----
547+
@Bean
548+
public AnnotationTemplateExpressionDefaults templateDefaults() {
549+
return new AnnotationTemplateExpressionDeafults();
550+
}
551+
----
552+
553+
Kotlin::
554+
+
555+
[source,kotlin,role="secondary"]
556+
----
557+
@Bean
558+
fun templateDefaults(): AnnotationTemplateExpressionDefaults {
559+
return AnnotationTemplateExpressionDeafults()
560+
}
561+
----
562+
563+
Xml::
564+
+
565+
[source,xml,role="secondary"]
566+
----
567+
<b:bean name="annotationExpressionTemplateDefaults" class="org.springframework.security.core.annotation.AnnotationTemplateExpressionDefaults"/>
568+
----
569+
======
570+
571+
and then you can supply a parameter to `@CurrentUser` like so:
572+
573+
[tabs]
574+
======
575+
Java::
576+
+
577+
[source,java,role="primary"]
578+
----
579+
@Target({ElementType.PARAMETER, ElementType.TYPE})
580+
@Retention(RetentionPolicy.RUNTIME)
581+
@Documented
582+
@AuthenticationPrincipal(expression = "claims['{claim}']")
583+
public @interface CurrentUser {
584+
String claim() default 'sub';
585+
}
586+
----
587+
588+
Kotlin::
589+
+
590+
[source,kotlin,role="secondary"]
591+
----
592+
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
593+
@Retention(AnnotationRetention.RUNTIME)
594+
@MustBeDocumented
595+
@AuthenticationPrincipal(expression = "claims['{claim}']")
596+
annotation class CurrentUser(val claim: String = "sub")
597+
----
598+
======
599+
600+
This will allow you more flexibility across your set of applications in the following way:
601+
602+
[tabs]
603+
======
604+
Java::
605+
+
606+
[source,java,role="primary"]
607+
----
608+
@RequestMapping("/messages/inbox")
609+
public ModelAndView findMessagesForUser(@CurrentUser("user_id") String userId) {
610+
611+
// .. find messages for this user and return them ...
612+
}
613+
----
614+
615+
Kotlin::
616+
+
617+
[source,kotlin,role="secondary"]
618+
----
619+
@RequestMapping("/messages/inbox")
620+
open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndView {
621+
622+
// .. find messages for this user and return them ...
623+
}
624+
----
625+
======
506626

507627
[[mvc-async]]
508628
== Spring MVC Async Integration

0 commit comments

Comments
 (0)