auth.go raw
1 // Code generated by smithy-go-codegen DO NOT EDIT.
2
3 package ssooidc
4
5 import (
6 "context"
7 "fmt"
8 awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
9 smithy "github.com/aws/smithy-go"
10 smithyauth "github.com/aws/smithy-go/auth"
11 "github.com/aws/smithy-go/metrics"
12 "github.com/aws/smithy-go/middleware"
13 "github.com/aws/smithy-go/tracing"
14 smithyhttp "github.com/aws/smithy-go/transport/http"
15 "slices"
16 "strings"
17 )
18
19 func bindAuthParamsRegion(_ interface{}, params *AuthResolverParameters, _ interface{}, options Options) error {
20 params.Region = options.Region
21 return nil
22 }
23
24 type setLegacyContextSigningOptionsMiddleware struct {
25 }
26
27 func (*setLegacyContextSigningOptionsMiddleware) ID() string {
28 return "setLegacyContextSigningOptions"
29 }
30
31 func (m *setLegacyContextSigningOptionsMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
32 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
33 ) {
34 rscheme := getResolvedAuthScheme(ctx)
35 schemeID := rscheme.Scheme.SchemeID()
36
37 if sn := awsmiddleware.GetSigningName(ctx); sn != "" {
38 if schemeID == "aws.auth#sigv4" {
39 smithyhttp.SetSigV4SigningName(&rscheme.SignerProperties, sn)
40 } else if schemeID == "aws.auth#sigv4a" {
41 smithyhttp.SetSigV4ASigningName(&rscheme.SignerProperties, sn)
42 }
43 }
44
45 if sr := awsmiddleware.GetSigningRegion(ctx); sr != "" {
46 if schemeID == "aws.auth#sigv4" {
47 smithyhttp.SetSigV4SigningRegion(&rscheme.SignerProperties, sr)
48 } else if schemeID == "aws.auth#sigv4a" {
49 smithyhttp.SetSigV4ASigningRegions(&rscheme.SignerProperties, []string{sr})
50 }
51 }
52
53 return next.HandleFinalize(ctx, in)
54 }
55
56 func addSetLegacyContextSigningOptionsMiddleware(stack *middleware.Stack) error {
57 return stack.Finalize.Insert(&setLegacyContextSigningOptionsMiddleware{}, "Signing", middleware.Before)
58 }
59
60 type withAnonymous struct {
61 resolver AuthSchemeResolver
62 }
63
64 var _ AuthSchemeResolver = (*withAnonymous)(nil)
65
66 func (v *withAnonymous) ResolveAuthSchemes(ctx context.Context, params *AuthResolverParameters) ([]*smithyauth.Option, error) {
67 opts, err := v.resolver.ResolveAuthSchemes(ctx, params)
68 if err != nil {
69 return nil, err
70 }
71
72 opts = append(opts, &smithyauth.Option{
73 SchemeID: smithyauth.SchemeIDAnonymous,
74 })
75 return opts, nil
76 }
77
78 func wrapWithAnonymousAuth(options *Options) {
79 if _, ok := options.AuthSchemeResolver.(*defaultAuthSchemeResolver); !ok {
80 return
81 }
82
83 options.AuthSchemeResolver = &withAnonymous{
84 resolver: options.AuthSchemeResolver,
85 }
86 }
87
88 // AuthResolverParameters contains the set of inputs necessary for auth scheme
89 // resolution.
90 type AuthResolverParameters struct {
91 // The name of the operation being invoked.
92 Operation string
93
94 // The region in which the operation is being invoked.
95 Region string
96 }
97
98 func bindAuthResolverParams(ctx context.Context, operation string, input interface{}, options Options) (*AuthResolverParameters, error) {
99 params := &AuthResolverParameters{
100 Operation: operation,
101 }
102
103 if err := bindAuthParamsRegion(ctx, params, input, options); err != nil {
104 return nil, err
105 }
106
107 return params, nil
108 }
109
110 // AuthSchemeResolver returns a set of possible authentication options for an
111 // operation.
112 type AuthSchemeResolver interface {
113 ResolveAuthSchemes(context.Context, *AuthResolverParameters) ([]*smithyauth.Option, error)
114 }
115
116 type defaultAuthSchemeResolver struct{}
117
118 var _ AuthSchemeResolver = (*defaultAuthSchemeResolver)(nil)
119
120 func (*defaultAuthSchemeResolver) ResolveAuthSchemes(ctx context.Context, params *AuthResolverParameters) ([]*smithyauth.Option, error) {
121 if overrides, ok := operationAuthOptions[params.Operation]; ok {
122 return overrides(params), nil
123 }
124 return serviceAuthOptions(params), nil
125 }
126
127 var operationAuthOptions = map[string]func(*AuthResolverParameters) []*smithyauth.Option{
128 "CreateToken": func(params *AuthResolverParameters) []*smithyauth.Option {
129 return []*smithyauth.Option{
130 {SchemeID: smithyauth.SchemeIDAnonymous},
131 }
132 },
133
134 "RegisterClient": func(params *AuthResolverParameters) []*smithyauth.Option {
135 return []*smithyauth.Option{
136 {SchemeID: smithyauth.SchemeIDAnonymous},
137 }
138 },
139
140 "StartDeviceAuthorization": func(params *AuthResolverParameters) []*smithyauth.Option {
141 return []*smithyauth.Option{
142 {SchemeID: smithyauth.SchemeIDAnonymous},
143 }
144 },
145 }
146
147 func serviceAuthOptions(params *AuthResolverParameters) []*smithyauth.Option {
148 return []*smithyauth.Option{
149 {
150 SchemeID: smithyauth.SchemeIDSigV4,
151 SignerProperties: func() smithy.Properties {
152 var props smithy.Properties
153 smithyhttp.SetSigV4SigningName(&props, "sso-oauth")
154 smithyhttp.SetSigV4SigningRegion(&props, params.Region)
155 return props
156 }(),
157 },
158 }
159 }
160
161 type resolveAuthSchemeMiddleware struct {
162 operation string
163 options Options
164 }
165
166 func (*resolveAuthSchemeMiddleware) ID() string {
167 return "ResolveAuthScheme"
168 }
169
170 func (m *resolveAuthSchemeMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
171 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
172 ) {
173 _, span := tracing.StartSpan(ctx, "ResolveAuthScheme")
174 defer span.End()
175
176 params, err := bindAuthResolverParams(ctx, m.operation, getOperationInput(ctx), m.options)
177 if err != nil {
178 return out, metadata, fmt.Errorf("bind auth scheme params: %w", err)
179 }
180 options, err := m.options.AuthSchemeResolver.ResolveAuthSchemes(ctx, params)
181 if err != nil {
182 return out, metadata, fmt.Errorf("resolve auth scheme: %w", err)
183 }
184
185 scheme, ok := m.selectScheme(options)
186 if !ok {
187 return out, metadata, fmt.Errorf("could not select an auth scheme")
188 }
189
190 ctx = setResolvedAuthScheme(ctx, scheme)
191
192 span.SetProperty("auth.scheme_id", scheme.Scheme.SchemeID())
193 span.End()
194 return next.HandleFinalize(ctx, in)
195 }
196
197 func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) (*resolvedAuthScheme, bool) {
198 sorted := sortAuthOptions(options, m.options.AuthSchemePreference)
199 for _, option := range sorted {
200 if option.SchemeID == smithyauth.SchemeIDAnonymous {
201 return newResolvedAuthScheme(smithyhttp.NewAnonymousScheme(), option), true
202 }
203
204 for _, scheme := range m.options.AuthSchemes {
205 if scheme.SchemeID() != option.SchemeID {
206 continue
207 }
208
209 if scheme.IdentityResolver(m.options) != nil {
210 return newResolvedAuthScheme(scheme, option), true
211 }
212 }
213 }
214
215 return nil, false
216 }
217
218 func sortAuthOptions(options []*smithyauth.Option, preferred []string) []*smithyauth.Option {
219 byPriority := make([]*smithyauth.Option, 0, len(options))
220 for _, prefName := range preferred {
221 for _, option := range options {
222 optName := option.SchemeID
223 if parts := strings.Split(option.SchemeID, "#"); len(parts) == 2 {
224 optName = parts[1]
225 }
226 if prefName == optName {
227 byPriority = append(byPriority, option)
228 }
229 }
230 }
231 for _, option := range options {
232 if !slices.ContainsFunc(byPriority, func(o *smithyauth.Option) bool {
233 return o.SchemeID == option.SchemeID
234 }) {
235 byPriority = append(byPriority, option)
236 }
237 }
238 return byPriority
239 }
240
241 type resolvedAuthSchemeKey struct{}
242
243 type resolvedAuthScheme struct {
244 Scheme smithyhttp.AuthScheme
245 IdentityProperties smithy.Properties
246 SignerProperties smithy.Properties
247 }
248
249 func newResolvedAuthScheme(scheme smithyhttp.AuthScheme, option *smithyauth.Option) *resolvedAuthScheme {
250 return &resolvedAuthScheme{
251 Scheme: scheme,
252 IdentityProperties: option.IdentityProperties,
253 SignerProperties: option.SignerProperties,
254 }
255 }
256
257 func setResolvedAuthScheme(ctx context.Context, scheme *resolvedAuthScheme) context.Context {
258 return middleware.WithStackValue(ctx, resolvedAuthSchemeKey{}, scheme)
259 }
260
261 func getResolvedAuthScheme(ctx context.Context) *resolvedAuthScheme {
262 v, _ := middleware.GetStackValue(ctx, resolvedAuthSchemeKey{}).(*resolvedAuthScheme)
263 return v
264 }
265
266 type getIdentityMiddleware struct {
267 options Options
268 }
269
270 func (*getIdentityMiddleware) ID() string {
271 return "GetIdentity"
272 }
273
274 func (m *getIdentityMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
275 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
276 ) {
277 innerCtx, span := tracing.StartSpan(ctx, "GetIdentity")
278 defer span.End()
279
280 rscheme := getResolvedAuthScheme(innerCtx)
281 if rscheme == nil {
282 return out, metadata, fmt.Errorf("no resolved auth scheme")
283 }
284
285 resolver := rscheme.Scheme.IdentityResolver(m.options)
286 if resolver == nil {
287 return out, metadata, fmt.Errorf("no identity resolver")
288 }
289
290 identity, err := timeOperationMetric(ctx, "client.call.resolve_identity_duration",
291 func() (smithyauth.Identity, error) {
292 return resolver.GetIdentity(innerCtx, rscheme.IdentityProperties)
293 },
294 func(o *metrics.RecordMetricOptions) {
295 o.Properties.Set("auth.scheme_id", rscheme.Scheme.SchemeID())
296 })
297 if err != nil {
298 return out, metadata, fmt.Errorf("get identity: %w", err)
299 }
300
301 ctx = setIdentity(ctx, identity)
302
303 span.End()
304 return next.HandleFinalize(ctx, in)
305 }
306
307 type identityKey struct{}
308
309 func setIdentity(ctx context.Context, identity smithyauth.Identity) context.Context {
310 return middleware.WithStackValue(ctx, identityKey{}, identity)
311 }
312
313 func getIdentity(ctx context.Context) smithyauth.Identity {
314 v, _ := middleware.GetStackValue(ctx, identityKey{}).(smithyauth.Identity)
315 return v
316 }
317
318 type signRequestMiddleware struct {
319 options Options
320 }
321
322 func (*signRequestMiddleware) ID() string {
323 return "Signing"
324 }
325
326 func (m *signRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
327 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
328 ) {
329 _, span := tracing.StartSpan(ctx, "SignRequest")
330 defer span.End()
331
332 req, ok := in.Request.(*smithyhttp.Request)
333 if !ok {
334 return out, metadata, fmt.Errorf("unexpected transport type %T", in.Request)
335 }
336
337 rscheme := getResolvedAuthScheme(ctx)
338 if rscheme == nil {
339 return out, metadata, fmt.Errorf("no resolved auth scheme")
340 }
341
342 identity := getIdentity(ctx)
343 if identity == nil {
344 return out, metadata, fmt.Errorf("no identity")
345 }
346
347 signer := rscheme.Scheme.Signer()
348 if signer == nil {
349 return out, metadata, fmt.Errorf("no signer")
350 }
351
352 _, err = timeOperationMetric(ctx, "client.call.signing_duration", func() (any, error) {
353 return nil, signer.SignRequest(ctx, req, identity, rscheme.SignerProperties)
354 }, func(o *metrics.RecordMetricOptions) {
355 o.Properties.Set("auth.scheme_id", rscheme.Scheme.SchemeID())
356 })
357 if err != nil {
358 return out, metadata, fmt.Errorf("sign request: %w", err)
359 }
360
361 span.End()
362 return next.HandleFinalize(ctx, in)
363 }
364