Skip to content

Commit 136f801

Browse files
committed
Document @AuthenticationPrincipal meta-annotations
Issue gh-15286
1 parent 25edd68 commit 136f801

File tree

1 file changed

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

1 file changed

+113
-0
lines changed

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

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,119 @@ 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+
564+
and then you can supply a parameter to `@CurrentUser` like so:
565+
566+
[tabs]
567+
======
568+
Java::
569+
+
570+
[source,java,role="primary"]
571+
----
572+
@Target({ElementType.PARAMETER, ElementType.TYPE})
573+
@Retention(RetentionPolicy.RUNTIME)
574+
@Documented
575+
@AuthenticationPrincipal(expression = "claims['{claim}']")
576+
public @interface CurrentUser {
577+
String claim() default 'sub';
578+
}
579+
----
580+
581+
Kotlin::
582+
+
583+
[source,kotlin,role="secondary"]
584+
----
585+
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE)
586+
@Retention(AnnotationRetention.RUNTIME)
587+
@MustBeDocumented
588+
@AuthenticationPrincipal(expression = "claims['{claim}']")
589+
annotation class CurrentUser(val claim: String = "sub")
590+
----
591+
======
592+
593+
This will allow you more flexibility across your set of applications in the following way:
594+
595+
[tabs]
596+
======
597+
Java::
598+
+
599+
[source,java,role="primary"]
600+
----
601+
@RequestMapping("/messages/inbox")
602+
public ModelAndView findMessagesForUser(@CurrentUser("user_id") String userId) {
603+
604+
// .. find messages for this user and return them ...
605+
}
606+
----
607+
608+
Kotlin::
609+
+
610+
[source,kotlin,role="secondary"]
611+
----
612+
@RequestMapping("/messages/inbox")
613+
open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndView {
614+
615+
// .. find messages for this user and return them ...
616+
}
617+
----
618+
======
506619

507620
[[mvc-async]]
508621
== Spring MVC Async Integration

0 commit comments

Comments
 (0)